]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_transform/lib/SecSignVerifyTransform.c
Security-57336.1.9.tar.gz
[apple/security.git] / Security / libsecurity_transform / lib / SecSignVerifyTransform.c
diff --git a/Security/libsecurity_transform/lib/SecSignVerifyTransform.c b/Security/libsecurity_transform/lib/SecSignVerifyTransform.c
deleted file mode 100644 (file)
index 37fbcb2..0000000
+++ /dev/null
@@ -1,725 +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 "SecSignVerifyTransform.h"
-#include "SecCustomTransform.h"
-#include "Utilities.h"
-#include <Security/Security.h>
-#include "misc.h"
-
-
-const static CFStringRef SignName = CFSTR("com.apple.security.Sign"), VerifyName = CFSTR("com.apple.security.Verify");
-CFStringRef kSecKeyAttributeName = CFSTR("KEY"), kSecSignatureAttributeName = CFSTR("Signature"), kSecInputIsAttributeName = CFSTR("InputIs");
-// Internally we force kSecInputIsAttributeName to one of these 3 things, you can use == rather then CFStringCompare once that happens
-CFStringRef kSecInputIsPlainText = CFSTR("PlainText"), kSecInputIsDigest = CFSTR("Digest"), kSecInputIsRaw = CFSTR("Raw");
-
-static
-CFErrorRef do_sec_fail(OSStatus code, const char *func, const char *file, int line) {
-       CFStringRef msg = CFStringCreateWithFormat(NULL, NULL, CFSTR("Internal error #%x at %s %s:%d"), (unsigned)code, func, file, line);
-       CFErrorRef err = fancy_error(CFSTR("Internal CSSM error"), code, msg);
-       CFRelease(msg);
-       
-       return err;
-}
-#define SEC_FAIL(err) if (err) { \
-    SecTransformCustomSetAttribute(ref, kSecTransformAbortAttributeName, kSecTransformMetaAttributeValue, do_sec_fail(err, __func__, __FILE__, __LINE__)); \
-    return (CFTypeRef)NULL; \
-}
-#define GET_SEC_FAIL(err) do_sec_fail(err, __func__, __FILE__, __LINE__)
-
-static
-CFErrorRef accumulate_data(CFMutableArrayRef *a, CFDataRef d) {
-       if (!*a) {
-               *a = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-               if (!*a) {
-                       return GetNoMemoryError();
-               }
-       }
-       CFDataRef dc = CFDataCreateCopy(NULL, d);
-       if (!dc) {
-               return GetNoMemoryError();
-       }
-       CFIndex c = CFArrayGetCount(*a);
-       CFArrayAppendValue(*a, dc);
-       CFRelease(dc);
-       if (CFArrayGetCount(*a) != c+1) {
-               return GetNoMemoryError();
-       }
-       
-       return NULL;
-}
-
-static
-CFErrorRef fetch_and_clear_accumulated_data(CFMutableArrayRef *a, CFDataRef *data_out) {
-       if (!*a) {
-               *data_out = CFDataCreate(NULL, NULL, 0);
-               return (*data_out) ? NULL : GetNoMemoryError();
-       }
-
-       CFIndex i, c = CFArrayGetCount(*a);
-       CFIndex total = 0, prev_total = 0;
-       
-       for(i = 0; i < c; i++) {
-               total += CFDataGetLength((CFDataRef)CFArrayGetValueAtIndex(*a, i));
-               if (total < prev_total) {
-                       return GetNoMemoryError();
-               }
-               prev_total = total;
-       }
-       
-       CFMutableDataRef out = CFDataCreateMutable(NULL, total);
-       if (!out) {
-               return GetNoMemoryError();
-       }
-       
-       for(i = 0; i < c; i++) {
-               CFDataRef d = (CFDataRef)CFArrayGetValueAtIndex(*a, i);
-               CFDataAppendBytes(out, CFDataGetBytePtr(d), CFDataGetLength(d));
-       }
-       
-       if (CFDataGetLength(out) != total) {
-               CFRelease(out);
-               return GetNoMemoryError();
-       }
-       
-       CFArrayRef accumulator = *a;
-       CFRelease(accumulator);
-       *a = NULL;
-       
-       // This might be nice:
-       //   *data_out = CFDataCreateCopy(NULL, out);
-       //   CFRelease(out);
-       // but that is slow (for large values) AND isn't really all that important anyway
-       
-       *data_out = out;
-       
-       return NULL;
-}
-
-struct digest_mapping {
-       // These 3 values are "search values"
-       CSSM_ALGORITHMS kclass;
-       CFStringRef digest_name;
-       int digest_length;
-       
-       // "data values"
-       CSSM_ALGORITHMS plain_text_algo, digest_algo;
-};
-
-static
-Boolean digest_mapping_equal(struct digest_mapping *a, struct digest_mapping *b) {
-       if (a == b) {
-               return TRUE;
-       }
-       
-       if (a->kclass == b->kclass && a->digest_length == b->digest_length && !CFStringCompare(a->digest_name, b->digest_name, 0)) {
-               return TRUE;
-       }
-       
-       return FALSE;
-}
-
-static
-CFHashCode digest_mapping_hash(struct digest_mapping *dm) {
-       return CFHash(dm->digest_name) + dm->kclass + dm->digest_length;
-}
-
-static
-CSSM_ALGORITHMS alg_for_signature_context(CFStringRef input_is, const struct digest_mapping *dm) {
-       if (!CFStringCompare(kSecInputIsPlainText, input_is, 0)) {
-               return dm->plain_text_algo;
-       } else if (!CFStringCompare(kSecInputIsDigest, input_is, 0) || !CFStringCompare(kSecInputIsRaw, input_is, 0)) {
-               return dm->kclass;
-       } else {
-               return CSSM_ALGID_NONE;
-       }
-}
-
-static
-CFErrorRef pick_sign_alg(CFStringRef digest, int digest_length, const CSSM_KEY *ckey, struct digest_mapping **picked) {
-       static dispatch_once_t once = 0;
-       static CFMutableSetRef algos = NULL;
-
-       dispatch_once(&once, ^{
-               struct digest_mapping digest_mappings_stack[] = {
-                       {CSSM_ALGID_RSA, kSecDigestSHA1, 0,   CSSM_ALGID_SHA1WithRSA, CSSM_ALGID_SHA1},
-                       {CSSM_ALGID_RSA, kSecDigestSHA1, 160,   CSSM_ALGID_SHA1WithRSA, CSSM_ALGID_SHA1},
-                       
-                       {CSSM_ALGID_RSA, kSecDigestMD2, 0,   CSSM_ALGID_MD2WithRSA, CSSM_ALGID_MD2},
-                       {CSSM_ALGID_RSA, kSecDigestMD2, 128,   CSSM_ALGID_MD2WithRSA, CSSM_ALGID_MD2},
-                       
-                       {CSSM_ALGID_RSA, kSecDigestMD5, 0,   CSSM_ALGID_MD5WithRSA, CSSM_ALGID_MD5},
-                       {CSSM_ALGID_RSA, kSecDigestMD5, 128,   CSSM_ALGID_MD5WithRSA, CSSM_ALGID_MD5},
-                       
-                       {CSSM_ALGID_RSA, kSecDigestSHA2, 0,   CSSM_ALGID_SHA512WithRSA, CSSM_ALGID_SHA512},
-                       {CSSM_ALGID_RSA, kSecDigestSHA2, 512,   CSSM_ALGID_SHA512WithRSA, CSSM_ALGID_SHA512},
-                       {CSSM_ALGID_RSA, kSecDigestSHA2, 384,   CSSM_ALGID_SHA384WithRSA, CSSM_ALGID_SHA384},
-                       {CSSM_ALGID_RSA, kSecDigestSHA2, 256,   CSSM_ALGID_SHA256WithRSA, CSSM_ALGID_SHA256},
-                       {CSSM_ALGID_RSA, kSecDigestSHA2, 224,   CSSM_ALGID_SHA224WithRSA, CSSM_ALGID_SHA224},
-                       
-                       
-                       {CSSM_ALGID_ECDSA, kSecDigestSHA1, 0,   CSSM_ALGID_SHA1WithECDSA, CSSM_ALGID_SHA1},
-                       {CSSM_ALGID_ECDSA, kSecDigestSHA1, 160,   CSSM_ALGID_SHA1WithECDSA, CSSM_ALGID_SHA1},
-                       
-                       {CSSM_ALGID_ECDSA, kSecDigestSHA2, 0,   CSSM_ALGID_SHA512WithECDSA, CSSM_ALGID_SHA512},
-                       {CSSM_ALGID_ECDSA, kSecDigestSHA2, 512,   CSSM_ALGID_SHA512WithECDSA, CSSM_ALGID_SHA512},
-                       {CSSM_ALGID_ECDSA, kSecDigestSHA2, 384,   CSSM_ALGID_SHA384WithECDSA, CSSM_ALGID_SHA384},
-                       {CSSM_ALGID_ECDSA, kSecDigestSHA2, 256,   CSSM_ALGID_SHA256WithECDSA, CSSM_ALGID_SHA256},
-                       {CSSM_ALGID_ECDSA, kSecDigestSHA2, 224,   CSSM_ALGID_SHA224WithECDSA, CSSM_ALGID_SHA224},
-                       
-                       {CSSM_ALGID_DSA, kSecDigestSHA1, 0,   CSSM_ALGID_SHA1WithDSA, CSSM_ALGID_SHA1},
-                       {CSSM_ALGID_DSA, kSecDigestSHA1, 160,   CSSM_ALGID_SHA1WithDSA, CSSM_ALGID_SHA1},
-               };
-               
-               CFIndex mapping_count = sizeof(digest_mappings_stack)/sizeof(digest_mappings_stack[0]);
-               void *digest_mappings = malloc(sizeof(digest_mappings_stack));
-               memcpy(digest_mappings, digest_mappings_stack, sizeof(digest_mappings_stack));
-
-               CFSetCallBacks dmcb = { .version = 0, .retain = NULL, .release = NULL, .copyDescription = NULL, .equal = (CFSetEqualCallBack)digest_mapping_equal, .hash = (CFSetHashCallBack)digest_mapping_hash };
-               
-               algos = CFSetCreateMutable(NULL, mapping_count, &dmcb);
-               int i;
-               for(i = 0; i < mapping_count; i++) {
-                       CFSetAddValue(algos, i + (struct digest_mapping *)digest_mappings);
-               }
-       });
-       
-       struct digest_mapping search;
-       search.kclass = ckey->KeyHeader.AlgorithmId;
-       search.digest_name = digest;
-       search.digest_length = digest_length;
-       
-       struct digest_mapping *dmapping = (void*)CFSetGetValue(algos, &search);
-       
-       if (dmapping) {
-               *picked = dmapping;
-               return NULL;
-       }
-       
-       // It is argueable better to gennerate these messages by looking at digest_mappings, but with only 3 keytypes and 4 digests (only one of which has signifigant length variations) a case statment is likely the best way.
-       switch (ckey->KeyHeader.AlgorithmId) {
-               case CSSM_ALGID_RSA:
-                       return fancy_error(kSecTransformErrorDomain, kSecTransformErrorInvalidAlgorithm, CFSTR("Invalid digest algorithm for RSA signature, choose one of: SHA1, SHA2 (512bits, 348bits, 256bits, or 224 bits), MD2, or MD5"));
-                       break;
-                       
-               case CSSM_ALGID_ECDSA:
-                       return fancy_error(kSecTransformErrorDomain, kSecTransformErrorInvalidAlgorithm, CFSTR("Invalid digest algorithm for ECDSA signature, choose one of: SHA1, or SHA2 (512bits, 348bits, 256bits, or 224 bits)"));
-                       break;
-                       
-               case CSSM_ALGID_DSA:
-                       return fancy_error(kSecTransformErrorDomain, kSecTransformErrorInvalidAlgorithm, CFSTR("Invalid digest algorithm for DSA signature, only SHA1 is supported"));
-                       break;
-                       
-               default:
-                       return fancy_error(kSecTransformErrorDomain, kSecTransformErrorInvalidAlgorithm, CFSTR("Expected key to be RSA, DSA or ECDSA key"));
-       }
-}
-
-static SecTransformInstanceBlock SignTransform(CFStringRef name, 
-                                                       SecTransformRef newTransform, 
-                                                       SecTransformImplementationRef ref)
-{
-       SecTransformInstanceBlock instanceBlock = ^
-       {
-               CFErrorRef result = NULL;
-               SecTransformCustomSetAttribute(ref, kSecKeyAttributeName, kSecTransformMetaAttributeRequired, kCFBooleanTrue);
-               SecTransformCustomSetAttribute(ref, kSecInputIsAttributeName, kSecTransformMetaAttributeRequired, kCFBooleanTrue);
-
-               __block CSSM_CC_HANDLE cch;
-               __block SecKeyRef key = NULL;
-               __block SecTransformDataBlock first_process_data = NULL;
-               __block CFStringRef digest = NULL;
-               __block int digest_length = 0;
-               __block CFStringRef input_is = NULL;
-               __block CFMutableArrayRef data_accumulator = NULL;
-               __block struct digest_mapping *sign_alg;
-               
-               SecTransformDataBlock plain_text_process_data = 
-               ^(CFTypeRef value) 
-               {
-                       CFDataRef d = value;
-                       OSStatus rc;
-                       
-                       if (d) {
-                               CSSM_DATA c_d;
-                               c_d.Data = (void*)CFDataGetBytePtr(d);
-                               c_d.Length = CFDataGetLength(d);
-                               
-                               rc = CSSM_SignDataUpdate(cch, &c_d, 1);
-                               SEC_FAIL(rc);
-                       } else {
-                               CSSM_DATA sig;
-                               const int max_sig_size = 32*1024;
-                               unsigned char *sig_data = malloc(max_sig_size); 
-                               sig.Data = sig_data;
-                               sig.Length = max_sig_size;
-                               
-                               rc = CSSM_SignDataFinal(cch, &sig);
-                               SEC_FAIL(rc);
-                               assert(sig.Length <= 32*1024);
-                               CSSM_DeleteContext(cch);
-                               // Could use NoCopy and hold onto the allocation, and that will be a good idea when we can have it not so oversized
-                               CFDataRef result = CFDataCreate(NULL, sig.Data, sig.Length);
-                               SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName, kSecTransformMetaAttributeValue, result);
-                               CFRelease(result);
-                               free(sig_data);
-                               
-                               key = NULL;
-                               
-                               CFRelease(digest);
-                               digest = NULL;
-                               
-                               digest_length = 0;
-                               
-                               SecTransformSetDataAction(ref, kSecTransformActionProcessData,  first_process_data);
-                               
-                               return (CFTypeRef)NULL;
-                       }
-                       
-                       return SecTransformNoData();
-               };
-               
-               SecTransformDataBlock cooked_process_data = 
-               ^(CFTypeRef value) 
-               {
-                       CFDataRef d = value;
-                       if (d) {
-                               accumulate_data(&data_accumulator, d);
-                       } else {
-                               CSSM_DATA sig;
-                               const int max_sig_size = 32*1024;
-                               unsigned char *sig_data = malloc(max_sig_size); 
-                               sig.Data = sig_data;
-                               sig.Length = max_sig_size;
-                               
-                               CFDataRef alldata;
-                               CFErrorRef err = fetch_and_clear_accumulated_data(&data_accumulator, &alldata);
-                               if (err) {
-                                       return (CFTypeRef)err;
-                               }
-                               CSSM_DATA c_d;
-                               c_d.Data = (void*)CFDataGetBytePtr(alldata);
-                               c_d.Length = CFDataGetLength(alldata);
-                               
-                               OSStatus rc = CSSM_SignData(cch, &c_d, 1, (input_is == kSecInputIsDigest) ? sign_alg->digest_algo : CSSM_ALGID_NONE, &sig);
-                               SEC_FAIL(rc);
-                               CFRelease(alldata);
-                               
-                               assert(sig.Length <= 32*1024);
-                               CSSM_DeleteContext(cch);
-                               // Could use NoCopy and hold onto the allocation, and that will be a good idea when we can have it not so oversized
-                               CFDataRef result = CFDataCreate(NULL, sig.Data, sig.Length);
-                               SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName, kSecTransformMetaAttributeValue, result);
-                               CFRelease(result);
-                               free(sig_data);
-                               
-                               key = NULL;
-                               
-                               CFRelease(digest);
-                               digest = NULL;
-                               
-                               digest_length = 0;
-                               
-                               SecTransformSetDataAction(ref, kSecTransformActionProcessData, first_process_data);
-                               
-                               return (CFTypeRef)NULL;
-                       }
-                       
-                       return SecTransformNoData();
-               };
-                               
-               first_process_data = Block_copy(^(CFTypeRef value) 
-               {
-                       OSStatus rc;
-                       if (key && digest && input_is) 
-                       {
-                               const CSSM_KEY *cssm_key;
-                               rc = SecKeyGetCSSMKey(key, &cssm_key);
-                               SEC_FAIL(rc);
-                               
-                               CFErrorRef bad_alg = pick_sign_alg(digest, digest_length, cssm_key, &sign_alg);
-                               if (bad_alg) 
-                               {
-                                       return (CFTypeRef)bad_alg;
-                               }
-
-                               CSSM_CSP_HANDLE csp;
-                               rc = SecKeyGetCSPHandle(key, &csp);
-                               SEC_FAIL(rc);
-                               
-                               const CSSM_ACCESS_CREDENTIALS *access_cred;
-                               rc = SecKeyGetCredentials(key, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &access_cred);
-                               SEC_FAIL(rc);
-                               
-                               CSSM_CSP_CreateSignatureContext(csp, alg_for_signature_context(input_is, sign_alg), access_cred, cssm_key, &cch);
-                               SEC_FAIL(rc);
-                               
-                               rc = CSSM_SignDataInit(cch);
-                               SEC_FAIL(rc);
-                                                               
-                               SecTransformDataBlock pd = (input_is == kSecInputIsPlainText) ? plain_text_process_data : cooked_process_data;
-
-                               SecTransformSetDataAction(ref, kSecTransformActionProcessData, pd);
-                               return pd(value);
-                       } 
-                       else 
-                       {
-                               SecTransformPushbackAttribute(ref, kSecTransformInputAttributeName, value);
-                               return SecTransformNoData();
-                       }
-               });
-               
-               SecTransformSetDataAction(ref, kSecTransformActionProcessData, first_process_data);
-               
-               SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification, kSecDigestTypeAttribute, 
-                       ^(SecTransformAttributeRef ah, CFTypeRef value) 
-                       {
-                               digest = CFRetain(value);
-                               return value;
-                       });
-
-               SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification, kSecKeyAttributeName, 
-                       ^(SecTransformAttributeRef ah, CFTypeRef value) 
-                       {
-                               if (value == NULL) {
-                    return value;
-                }
-                
-                const CSSM_KEY *cssm_key;
-                               key = (SecKeyRef)value;
-                       
-                               OSStatus rc = SecKeyGetCSSMKey(key, &cssm_key);
-                               SEC_FAIL(rc);
-                       
-                               if (!cssm_key->KeyHeader.KeyUsage & CSSM_KEYUSE_SIGN)
-                               {
-                                       key = NULL;
-                    
-                    CFTypeRef error = CreateSecTransformErrorRef(kSecTransformErrorInvalidInput, "Key %@ can not be used to sign", key);
-                                       SecTransformCustomSetAttribute(ref, kSecTransformAbortAttributeName, kSecTransformMetaAttributeValue, error);
-                    return (CFTypeRef)NULL;
-                               }
-                               return value;
-                       });
-               
-               SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification, kSecDigestLengthAttribute, 
-                       ^(SecTransformAttributeRef ah, CFTypeRef value) 
-                       {
-                               CFNumberGetValue(value, kCFNumberIntType, &digest_length);
-                               return value;
-                       });
-               
-               SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification, kSecInputIsAttributeName,
-                       ^(SecTransformAttributeRef ah, CFTypeRef value) 
-                       {
-                               if (!CFStringCompare(value, kSecInputIsPlainText, 0)) {
-                                       input_is = kSecInputIsPlainText;
-                               } else if (!CFStringCompare(value, kSecInputIsDigest, 0)) {
-                                       input_is = kSecInputIsDigest;
-                               } else if (!CFStringCompare(value, kSecInputIsRaw, 0)) {
-                                       input_is = kSecInputIsRaw;
-                               } else {
-                                       input_is = NULL;
-                                       return (CFTypeRef)fancy_error(kSecTransformErrorDomain, kSecTransformErrorInvalidType, CFSTR("InputIs should be one of: PlainText, Digest, or Raw"));
-                               }
-                               return (CFTypeRef)input_is;
-                       });                     
-               
-               SecTransformSetTransformAction(ref, kSecTransformActionFinalize, 
-                       ^{
-                               Block_release(first_process_data);
-                               return (CFTypeRef)NULL;
-                       });
-               
-               return result;
-       };
-               
-       return Block_copy(instanceBlock);       
-}
-                                                       
-SecTransformRef SecSignTransformCreate(SecKeyRef key, CFErrorRef* error)
-{      
-       static dispatch_once_t once;
-       __block Boolean ok = TRUE;
-                       
-       dispatch_block_t aBlock = ^
-       {
-               ok = SecTransformRegister(SignName, &SignTransform, error);
-       };
-       
-       dispatch_once(&once, aBlock);
-
-       if (!ok) 
-       {
-               return NULL;
-       }       
-       
-       SecTransformRef tr = SecTransformCreate(SignName, error);
-       if (!tr) {
-               return tr;
-       }
-       SecTransformSetAttribute(tr, kSecKeyAttributeName, key, error);
-       SecTransformSetAttribute(tr, kSecDigestTypeAttribute, kSecDigestSHA1, NULL);
-       SecTransformSetAttribute(tr, kSecInputIsAttributeName, kSecInputIsPlainText, NULL);
-       
-       return tr;
-}
-
-static SecTransformInstanceBlock VerifyTransform(CFStringRef name, 
-                                                       SecTransformRef newTransform, 
-                                                       SecTransformImplementationRef ref)
-{
-       SecTransformInstanceBlock instanceBlock = ^
-       {
-               CFErrorRef result = NULL;
-               SecTransformCustomSetAttribute(ref, kSecKeyAttributeName, kSecTransformMetaAttributeRequired, kCFBooleanTrue);
-               SecTransformCustomSetAttribute(ref, kSecSignatureAttributeName, kSecTransformMetaAttributeRequired, kCFBooleanTrue);
-               SecTransformCustomSetAttribute(ref, kSecInputIsAttributeName, kSecTransformMetaAttributeRequired, kCFBooleanTrue);
-               
-               __block CSSM_CC_HANDLE cch;
-               __block const CSSM_KEY *cssm_key;
-               __block CSSM_CSP_HANDLE csp;
-               __block const CSSM_ACCESS_CREDENTIALS *access_cred;
-               __block CFDataRef signature = NULL;
-               __block unsigned char had_last_input = 0;
-               __block CFStringRef digest = NULL;
-               __block int digest_length = 0;
-               __block SecTransformDataBlock first_process_data;
-               __block SecKeyRef key = NULL;
-               __block CFStringRef input_is = NULL;
-               __block CFMutableArrayRef data_accumulator = NULL;
-               __block struct digest_mapping *verify_alg = NULL;
-
-               SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification, kSecInputIsAttributeName, 
-                       ^(SecTransformAttributeRef ah, CFTypeRef value) 
-                       {
-                               if (!CFStringCompare(value, kSecInputIsPlainText, 0)) {
-                                       input_is = kSecInputIsPlainText;
-                               } else if (!CFStringCompare(value, kSecInputIsDigest, 0)) {
-                                       input_is = kSecInputIsDigest;
-                               } else if (!CFStringCompare(value, kSecInputIsRaw, 0)) {
-                                       input_is = kSecInputIsRaw;
-                               } else {
-                                       input_is = NULL;
-                                       return (CFTypeRef)fancy_error(kSecTransformErrorDomain, kSecTransformErrorInvalidType, CFSTR("InputIs should be one of: PlainText, Digest, or Raw"));
-                               }
-                               return (CFTypeRef)input_is;
-                       });                     
-               
-               SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification, kSecKeyAttributeName, 
-                       ^(SecTransformAttributeRef ah, CFTypeRef value) 
-                       {
-                               OSStatus rc;
-                
-                if (value == NULL) {
-                    return value;
-                }
-                       
-                               rc = SecKeyGetCSSMKey((SecKeyRef)value, &cssm_key);
-                               SEC_FAIL(rc);
-                       
-                               if (!cssm_key->KeyHeader.KeyUsage & CSSM_KEYUSE_VERIFY)
-                               {
-                                       // This key cannot verify!
-                                       return (CFTypeRef)CreateSecTransformErrorRef(kSecTransformErrorInvalidInput, "Key %@ can not be used to verify", key);
-                               }
-               
-                               // we don't need to retain this because the owning transform is doing that for us
-                               key = (SecKeyRef) value;
-                               return value;
-                       });
-               
-               // We call this when we get the last input and when we get the signature.   If both are true when it is 
-               // called we are really done, and it gennerates the output
-               void (^done)(void) = 
-               ^{
-                       if (signature && had_last_input) 
-                       {
-                               CSSM_DATA sig;
-                               OSStatus rc;
-                               sig.Data = (void*)CFDataGetBytePtr(signature);
-                               sig.Length = CFDataGetLength(signature);
-                               CFRelease(signature);
-                               signature = NULL;
-                               
-                               if (input_is == kSecInputIsPlainText) {
-                                       rc = CSSM_VerifyDataFinal(cch, &sig);
-                               } else {
-                                       CFDataRef alldata;
-                                       CFErrorRef err = fetch_and_clear_accumulated_data(&data_accumulator, &alldata);
-                                       if (err) {
-                                               SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName, kSecTransformMetaAttributeValue, (CFTypeRef)err);
-                                               return;
-                                       }
-                                       
-                                       CSSM_DATA c_d;
-                                       c_d.Data = (void*)CFDataGetBytePtr(alldata);
-                                       c_d.Length = CFDataGetLength(alldata);
-                                       rc = CSSM_VerifyData(cch, &c_d, 1, (input_is == kSecInputIsDigest) ? verify_alg->digest_algo : CSSM_ALGID_NONE, &sig);
-                    CFRelease(alldata);
-
-                               }
-                               CSSM_DeleteContext(cch);
-                               if (rc == 0 || rc == CSSMERR_CSP_VERIFY_FAILED) {
-                                       SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName, kSecTransformMetaAttributeValue, rc ? kCFBooleanFalse : kCFBooleanTrue);
-                                       SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName, kSecTransformMetaAttributeValue, NULL);
-                               } else {
-                                       SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName, kSecTransformMetaAttributeValue, GET_SEC_FAIL(rc));
-                               }
-                               had_last_input = FALSE;
-                               SecTransformSetDataAction(ref, kSecTransformActionProcessData, first_process_data);     
-                       }
-               };
-               
-               SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification, kSecSignatureAttributeName, 
-                       ^(SecTransformAttributeRef ah, CFTypeRef value) 
-                       {
-                               if (value) {
-                                       signature = CFRetain(value);
-                               }
-                       
-                               done();
-                       
-                               return (CFTypeRef)value;
-                       });
-               
-               SecTransformDataBlock process_data = 
-                       ^(CFTypeRef value) 
-                       {
-                               OSStatus rc;
-                               CFDataRef d = value;
-                       
-                               if (d) {
-                                       if (input_is == kSecInputIsPlainText) {
-                                               CSSM_DATA c_d;
-                                               c_d.Data = (void*)CFDataGetBytePtr(d);
-                                               c_d.Length = CFDataGetLength(d);
-                                       
-                                               rc = CSSM_VerifyDataUpdate(cch, &c_d, 1);
-                                               SEC_FAIL(rc);
-                                       } else {
-                                               accumulate_data(&data_accumulator, d);
-                                       }
-                               } else {
-                                       had_last_input = 1;
-                                       done();
-                               }
-                       
-                               return SecTransformNoData();
-                       };
-               
-               first_process_data = 
-                       ^(CFTypeRef value) 
-                       {
-                               if (key && digest && input_is) {
-                                       // XXX: For RSA keys, signal an error if the digest size>keysize
-                               
-                                       OSStatus rc = SecKeyGetCSPHandle(key, &csp);
-                                       SEC_FAIL(rc);
-                               
-                                       rc = SecKeyGetCredentials(key, CSSM_ACL_AUTHORIZATION_ANY, kSecCredentialTypeDefault, &access_cred);
-                                       SEC_FAIL(rc);
-                               
-                                       CFErrorRef bad_alg = pick_sign_alg(digest, digest_length, cssm_key, &verify_alg);
-                                       if (bad_alg) {
-                                               return (CFTypeRef)bad_alg;
-                                       }
-                               
-                                       CSSM_CSP_CreateSignatureContext(csp, alg_for_signature_context(input_is, verify_alg), NULL, cssm_key, &cch);
-                                       SEC_FAIL(rc);
-                               
-                                       rc = CSSM_VerifyDataInit(cch);
-                                       SEC_FAIL(rc);
-
-                                       SecTransformSetDataAction(ref, kSecTransformActionProcessData, process_data);
-                                       return process_data(value);
-                               } else {
-                                       SecTransformPushbackAttribute(ref, kSecTransformInputAttributeName, value);
-                                       return SecTransformNoData();
-                               }
-                       };
-               first_process_data = Block_copy(first_process_data);
-               
-               SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification, kSecDigestTypeAttribute, 
-                       ^(SecTransformAttributeRef ah, CFTypeRef value) 
-                       {
-                               digest = CFRetain(value);
-                               return value;
-                       });
-               
-               SecTransformSetTransformAction(ref, kSecTransformActionFinalize, 
-                       ^{
-                               Block_release(first_process_data);
-                               return (CFTypeRef)NULL;
-                       });
-               
-               SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification, kSecDigestLengthAttribute, 
-                       ^(SecTransformAttributeRef ah, CFTypeRef value) 
-                       {
-                               CFNumberGetValue(value, kCFNumberIntType, &digest_length);
-                               return value;
-                       });
-               
-               SecTransformSetDataAction(ref, kSecTransformActionProcessData, first_process_data);     
-               
-               return result;
-       };
-       
-       return Block_copy(instanceBlock);
-}
-
-SecTransformRef SecVerifyTransformCreate(SecKeyRef key, CFDataRef signature, CFErrorRef* error)
-{
-       static dispatch_once_t once;
-       __block Boolean ok = TRUE;
-                       
-       dispatch_block_t aBlock = ^
-       {
-               ok = SecTransformRegister(VerifyName, &VerifyTransform, error);
-       };
-       
-       dispatch_once(&once, aBlock);
-
-       if (!ok) 
-       {
-               return NULL;
-       }
-       
-       
-       SecTransformRef tr = SecTransformCreate(VerifyName, error);
-       if (!tr) {
-               return tr;
-       }
-       
-       SecTransformSetAttribute(tr, kSecKeyAttributeName, key, error);
-       if (signature) 
-       {
-               SecTransformSetAttribute(tr, kSecSignatureAttributeName, signature, error);
-       }
-       SecTransformSetAttribute(tr, kSecDigestTypeAttribute, kSecDigestSHA1, NULL);
-       SecTransformSetAttribute(tr, kSecDigestTypeAttribute, kSecDigestSHA1, NULL);
-       SecTransformSetAttribute(tr, kSecInputIsAttributeName, kSecInputIsPlainText, NULL);
-
-       return tr;
-}