X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/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 index 37fbcb25..00000000 --- a/Security/libsecurity_transform/lib/SecSignVerifyTransform.c +++ /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 -#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; -}