SecCustomTransform.h   [plain text]


/*
 * Copyright © 2010 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
 * 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@
 */

#ifndef _SEC_CUSTOM_TRANSFORM_H__
#define _SEC_CUSTOM_TRANSFORM_H__

#include <Security/SecTransform.h>

// Blocks are required for custom transforms
#ifdef __BLOCKS__

CF_EXTERN_C_BEGIN

/*!
    @header

    Custom transforms are an API that provides the ability to easily create new
    transforms. The essential functions of a transform are created in a
    collection of blocks. These blocks override the standard behavior of the
    base transform; a custom transform with no overrides is a null transform
    that merely passes through a data flow.

    A new transform type is created when calling the SecTransformRegister
    function which registers the name of the new transform and sets up its
    overrides. The SecTransformCreate function creates a new instance of a
    registered custom transform.

    A sample custom transform is provided here, along with a basic test program.
    This transform creates a Caesar cipher transform, one that simply adds a
    value to every byte of the plaintext.

    -----cut here-----
<pre>
@textblock
//
//  CaesarXform.c
//
//  Copyright 2010 Apple Inc. All rights reserved.
//
//

#include <Security/SecCustomTransform.h>
#include <Security/SecTransform.h>

// This is the unique name for the custom transform type.
const CFStringRef kCaesarCipher = CFSTR("com.apple.caesarcipher");

// Name of the "key" attribute.
const CFStringRef kKeyAttributeName = CFSTR("key");

// Shortcut to return a CFError.
CFErrorRef invalid_input_error(void)
{
    return CFErrorCreate(kCFAllocatorDefault, kSecTransformErrorDomain,
                         kSecTransformErrorInvalidInput, NULL);
}

// =========================================================================
//  Implementation of the Transform instance
// =========================================================================
static SecTransformInstanceBlock CaesarImplementation(CFStringRef name,
                                            SecTransformRef newTransform,
                                            SecTransformImplementationRef ref)
{
   
    SecTransformInstanceBlock instanceBlock =
    ^{
        CFErrorRef result = NULL;

        // Every time a new instance of this custom transform class is
        // created, this block is called. This behavior means that any
        // block variables created in this block act like instance
        // variables for the new custom transform instance.
        __block int _key = 0;

        result = SecTransformSetAttributeAction(ref,
                                                kSecTransformActionAttributeNotification,
                                                kKeyAttributeName,
                                                ^(SecTransformAttributeRef name, CFTypeRef d)
            {
                CFNumberGetValue((CFNumberRef)d, kCFNumberIntType, &_key);
                return d;
            });

        if (result)
            return result;

        // Create an override that will be called to process the input
        // data into the output data
        result = SecTransformSetDataAction(ref,
                                           kSecTransformActionProcessData,
                                           ^(CFTypeRef d)
            {
                if (NULL == d)               // End of stream?
                    return (CFTypeRef) NULL; // Just return a null.

                char *dataPtr = (char *)CFDataGetBytePtr((CFDataRef)d);

                CFIndex dataLength = CFDataGetLength((CFDataRef)d);

                // Do the processing in memory.  There are better ways to do
                // this but for showing how custom transforms work this is fine.
                char *buffer = (char *)malloc(dataLength);
                if (NULL == buffer)
                    return (CFTypeRef) invalid_input_error();            // Return a CFErrorRef

                // Do the work of the caesar cipher (Rot(n))

                CFIndex i;
                for (i = 0; i < dataLength; i++)
                    buffer[i] = dataPtr[i] + _key;

                return (CFTypeRef)CFDataCreateWithBytesNoCopy(NULL, (UInt8 *)buffer,
                                                              dataLength, kCFAllocatorMalloc);
            });
        return result;
    };

    return Block_copy(instanceBlock);
}

SecTransformRef CaesarTransformCreate(CFIndex k, CFErrorRef* error)
{
    SecTransformRef caesarCipher;
    __block Boolean result = 1;
    static dispatch_once_t registeredOK = 0;

    dispatch_once(&registeredOK,
                  ^{
                     result = SecTransformRegister(kCaesarCipher, &CaesarImplementation, error);
                  });

    if (!result)
        return NULL;

    caesarCipher = SecTransformCreate(kCaesarCipher, error);
    if (NULL != caesarCipher)
    {
        CFNumberRef keyNumber =  CFNumberCreate(kCFAllocatorDefault,
                                                kCFNumberIntType, &k);
        SecTransformSetAttribute(caesarCipher, kKeyAttributeName,
                                 keyNumber, error);
        CFRelease(keyNumber);
    }

    return caesarCipher;
}


// The second function shows how to use custom transform defined in the
// previous function

// =========================================================================
//  Use a custom ROT-N (caesar cipher) transform
// =========================================================================
CFDataRef TestCaesar(CFDataRef theData, int rotNumber)
{
    CFDataRef result = NULL;
    CFErrorRef error = NULL;

    if (NULL == theData)
        return result;

    // Create an instance of the custom transform
    SecTransformRef caesarCipher = CaesarTransformCreate(rotNumber, &error);
    if (NULL == caesarCipher || NULL != error)
        return result;

    // Set the data to be transformed as the input to the custom transform
    SecTransformSetAttribute(caesarCipher,
                             kSecTransformInputAttributeName, theData, &error);

    if (NULL != error)
    {
        CFRelease(caesarCipher);
        return result;
    }

    // Execute the transform synchronously
    result = (CFDataRef)SecTransformExecute(caesarCipher, &error);
    CFRelease(caesarCipher);

    return result;
}

#include <CoreFoundation/CoreFoundation.h>

int main (int argc, const char *argv[])
{
    CFDataRef testData, testResult;
    UInt8 bytes[26];
    int i;

    // Create some test data, a string from A-Z

    for (i = 0; i < sizeof(bytes); i++)
        bytes[i] = 'A' + i;

    testData = CFDataCreate(kCFAllocatorDefault, bytes, sizeof(bytes));
    CFRetain(testData);
    CFShow(testData);

    // Encrypt the test data
    testResult = TestCaesar(testData, 3);

    CFShow(testResult);
    CFRelease(testData);
    CFRelease(testResult);
    return 0;
}
@/textblock
</pre>
	
*/

/****************	Custom Transform attribute metadata   ****************/

/*!
    @enum Custom Transform Attribute Metadata
    @discussion
            Within a transform, each of its attributes is a collection of
            "metadata attributes", of which name and current value are two. The
            value is directly visible from outside; the other metadata
            attributes direct the behavior of the transform and
            its function within its group. Each attribute may be tailored by setting its metadata.

    @const kSecTransformMetaAttributeValue
            The actual value of the attribute. The attribute value has a default
            value of NULL.

    @const kSecTransformMetaAttributeName
            The name of the attribute. Attribute name is read only and may
            not be used with the SecTransformSetAttributeBlock block.

    @const kSecTransformMetaAttributeRef
            A direct reference to an attribute's value. This reference allows
            for direct access to an attribute without having to look up the
            attribute by name.  If a transform commonly uses an attribute, using
            a reference speeds up the use of that attribute. Attribute
            references are not visible or valid from outside of the particular
            transform instance.

    @const kSecTransformMetaAttributeRequired
            Specifies if an attribute must have a non NULL value set or have an
            incoming connection before the transform starts to execute. This
            metadata has a default value of true for the input attribute, but
            false for all other attributes.

    @const kSecTransformMetaAttributeRequiresOutboundConnection
            Specifies if an attribute must have an outbound connection. This
            metadata has a default value of true for the output attribute but is
            false for all other attributes.

    @const kSecTransformMetaAttributeDeferred
            Determines if the AttributeSetNotification notification or the
            ProcessData blocks are deferred until SecExecuteTransform is called.
            This metadata value has a default value of true for the input
            attribute but is false for all other attributes.

    @const kSecTransformMetaAttributeStream
            Specifies if the attribute should expect a series of values ending
            with a NULL to specify the end of the data stream. This metadata has
            a default value of true for the input and output attributes, but is
            false for all other attributes.

    @const kSecTransformMetaAttributeCanCycle
            A Transform group is a directed graph which is typically acyclic.
            Some transforms need to work with cycles. For example, a transform
            that emits a header and trailer around the data of another transform
            must create a cycle. If this metadata set to true, no error is
            returned if a cycle is detected for this attribute.

    @const kSecTransformMetaAttributeExternalize
            Specifies if this attribute should be written out when creating the
            external representation of this transform. This metadata has a
            default value of true.

    @const kSecTransformMetaAttributeHasOutboundConnections
            This metadata value is true if the attribute has an outbound
            connection. This metadata is read only.

    @const kSecTransformMetaAttributeHasInboundConnection
            This metadata value is true if the attribute has an inbound
            connection. This metadata is read only.
*/

enum
{
    kSecTransformMetaAttributeValue,
    kSecTransformMetaAttributeName,
    kSecTransformMetaAttributeRef,
    kSecTransformMetaAttributeRequired,
    kSecTransformMetaAttributeRequiresOutboundConnection,
    kSecTransformMetaAttributeDeferred,
    kSecTransformMetaAttributeStream,
    kSecTransformMetaAttributeCanCycle,
    kSecTransformMetaAttributeExternalize,
    kSecTransformMetaAttributeHasOutboundConnections,
    kSecTransformMetaAttributeHasInboundConnection
};

typedef CFIndex SecTransformMetaAttributeType;

/*!
    @typedef        SecTransformAttributeRef

    @abstract       A direct reference to an attribute. Using an attribute
                    reference speeds up using an attribute's value by removing
                    the need to look
    it up by name.
*/
typedef CFTypeRef SecTransformAttributeRef;


/*!
    @typedef        SecTransformStringOrAttributeRef

    @abstract       This type signifies that either a CFStringRef or
                    a SecTransformAttributeRef may be used.
*/
typedef CFTypeRef SecTransformStringOrAttributeRef;


/*!
    @typedef        SecTransformActionBlock

    @abstract       A block that overrides the default behavior of a
                    custom transform.

    @result         If this block is used to overide the
                    kSecTransformActionExternalizeExtraData action then the
                    block should return a CFDictinaryRef of the custom
                    items to be exported. For all of other actions the
                    block should return NULL. If an error occurs for
                    any action, the block should return a CFErrorRef.

    @discussion     A SecTransformTransformActionBlock block is used to
                    override
                    the default behavior of a custom transform. This block is
                    associated with the SecTransformOverrideTransformAction
                    block.

                    The behaviors that can be overridden are:

                        kSecTransformActionCanExecute
                            Determine if the transform has all of the data
                            needed to run.

                        kSecTransformActionStartingExecution
                            Called just before running ProcessData.

                        kSecTransformActionFinalize
                            Called just before deleting the custom transform.

                        kSecTransformActionExternalizeExtraData
                            Called to allow for writing out custom data
                            to be exported.

                    Example:
<pre>
@textblock
                    SecTransformImplementationRef ref;
                    CFErrorRef error = NULL;

                    error = SecTransformSetTransformAction(ref, kSecTransformActionStartingExecution,
                    ^{
                        // This is where the work to initialize any data needed
                        // before running
                        CFErrorRef result = DoMyInitialization();
                        return result;
                    });

                    SecTransformTransformActionBlock actionBlock =
                    ^{
                        // This is where the work to clean up any existing data
                        // before running
                        CFErrorRef result = DoMyFinalization();
                        return result;
                    };

                    error = SecTransformSetTransformAction(ref, kSecTransformActionFinalize,
                        actionBlock);
@/textblock
</pre>
*/
typedef CFTypeRef (^SecTransformActionBlock)(void);

/*!
    @typedef        SecTransformAttributeActionBlock

    @abstract       A block used to override the default attribute handling
                    for when an attribute is set.

    @param attribute       The attribute whose default is being overridden or NULL
                    if this is a generic notification override

    @param value    Proposed new value for the attribute.

    @result         The new value of the attribute if successful. If an
                    error occurred then a CFErrorRef is returned. If a transform
                    needs to have a CFErrorRef as the value of an attribute,
                    then the CFErrorRef needs to be placed into a container such
                    as a CFArrayRef, CFDictionaryRef etc.

    @discussion     See the example program in this header for more details.

*/
typedef CFTypeRef (^SecTransformAttributeActionBlock)(
                                SecTransformAttributeRef attribute,
                                CFTypeRef value);
                                
/*!
    @typedef        SecTransformDataBlock
    
    @abstract       A block used to override the default data handling 
                    for a transform.

    @param data     The data to be processed. When this block is used
                    to to implement the kSecTransformActionProcessData action,
                    the data is the input data that is to be processed into the
                    output data.  When this block is used to implement the
                    kSecTransformActionInternalizeExtraData action, the data is
                    a CFDictionaryRef that contains the data that needs to be
                    imported.

    @result         When this block is used to implment the 
                    kSecTransformActionProcessData action, the value returned
                    is to be the data that will be passed to the output
                    attribute.  If an error occured while processing the input
                    data then the block should return a CFErrorRef.

                    When this block is used to implement the
                    kSecTransformActionInternalizeExtraData action then this block
                    should return NULL or a CFErrorRef if an error occurred.

    @discussion     See the example program for more details.
*/
typedef CFTypeRef (^SecTransformDataBlock)(CFTypeRef data);

/*!
    @typedef        SecTransformInstanceBlock

    @abstract       This is the block that is returned from an 
                    implementation of a CreateTransform function.

    @result         A CFErrorRef if an error occurred or NULL.
    
    @discussion     The instance block that is returned from the
                    developers CreateTransform function, defines 
                    the behavior of a custom attribute.  Please
                    see the example at the head of this file.

*/
typedef CFErrorRef (^SecTransformInstanceBlock)(void);

/*!
    @typedef        SecTransformImplementationRef

    @abstract       The SecTransformImplementationRef is a pointer to a block 
                    that implements an instance of a transform.

*/
typedef const struct OpaqueSecTransformImplementation* SecTransformImplementationRef;

/*!
    @function       SecTransformSetAttributeAction

    @abstract       Be notified when a attribute is set. The supplied block is
                    called when the attribute is set. This can be done for a
                    specific named attribute or all attributes.

    @param ref      A SecTransformImplementationRef that is bound to an instance
                    of a custom transform.

    @param action   The behavior to be set. This can be one of the following
                    actions: 

                    kSecTransformActionAttributeNotification - add a block that
                    is called when an attribute is set. If the name is NULL,
                    then the supplied block is called for all set attributes
                    except for ones that have a specific block as a handler.

                    For example, if there is a handler for the attribute "foo"
                    and for all attributes, the "foo" handler is called when the
                    "foo" attribute is set, but all other attribute sets will
                    call the NULL handler.

                    The kSecTransformActionProcessData action is a special case
                    of a SecTransformSetAttributeAction action.  If this is
                    called on the input attribute then it will overwrite any
                    kSecTransformActionProcessData that was set.

                    kSecTransformActionAttributeValidation Add a block that is
                    called to validate the input to an attribute.

    @param attribute
                    The name of the attribute that will be handled. An attribute
                    reference may also be given here. A NULL name indicates that
                    the supplied action is for all attributes.

    @param newAction
                    A SecTransformAttributeActionBlock which implements the
                    behavior.

    @result         A CFErrorRef if an error occured NULL otherwise.

    @discussion     This function may be called multiple times for either a
                    named attribute or for all attributes when the attribute
                    parameter is NULL. Each time the API is called it overwrites
                    what was there previously.

*/
CF_EXPORT
CFErrorRef SecTransformSetAttributeAction(SecTransformImplementationRef ref,
                                CFStringRef action,
                                SecTransformStringOrAttributeRef attribute,
                                SecTransformAttributeActionBlock newAction);
/*!
    @function       SecTransformSetDataAction

    @abstract       Change the way a custom transform will do data processing.
                    When the action parameter is kSecTransformActionProcessData
                    The newAction block will change the way that input data is
                    processed to become the output data. When the action
                    parameter is kSecTransformActionInternalizeExtraData it will
                    change the way a custom transform reads in data to be
                    imported into the transform.

    @param ref      A SecTransformImplementationRef that is bound to an instance
                    of a custom transform.

    @param action   The action being overridden.  This value should be one of the
                    following:
                        kSecTransformActionProcessData
                            Change the way that input data is processed into the
                            output data. The default behavior is to simply copy
                            the input data to the output attribute.

                            The kSecTransformActionProcessData action is really
                            a special case of a SecTransformSetAttributeAction
                            action. If you call this method with
                            kSecTransformActionProcessData it would overwrite
                            any kSecTransformActionAttributeNotification action
                            that was set proviously

                        kSecTransformActionInternalizeExtraData
                            Change the way that custom externalized data is
                            imported into the transform.  The default behavior
                            is to do nothing.

    @param newAction
                    A SecTransformDataBlock which implements the behavior.

                    If the action parameter is kSecTransformActionProcessData then
                    this block will be called to process the input data into the
                    output data.

                    if the action parameter is kSecTransformActionInternalizeExtraData then
                    this block will called to input custom data into the transform.

    @result         A CFErrorRef is an error occured NULL otherwise.

    @discussion      This API may be called multiple times.  Each time the API is called 
                    it overwrites what was there previously.

*/
CF_EXPORT
CFErrorRef SecTransformSetDataAction(SecTransformImplementationRef ref,
                                    CFStringRef action,
                                    SecTransformDataBlock newAction);

/*
    @function       SecTransformSetTransformAction

    @abstract       Change the way that transform deals with transform lifecycle
                    behaviors.

    @param ref      A SecTransformImplementationRef that is bound to an instance
                    of a custom transform. It provides the neccessary context
                    for making the call to modify a custom transform.

    @param action   Defines what behavior will be changed.  The possible values
                    are:

                        kSecTransformActionCanExecute
                            A CanExecute block is called before the transform
                            starts to execute. Returning NULL indicates that the
                            transform has all necessary parameters set up to be
                            able to execute. If there is a condition that
                            prevents this transform from executing, return a
                            CFError. The default behavior is to return NULL.

                        kSecTransformActionStartingExecution
                            A StartingExecution block is called as a transform
                            starts execution but before any input is delivered.
                            Transform-specific initialization can be performed
                            in this block.

                        kSecTransformActionFinalize
                            A Finalize block is called before a transform is
                            released. Any final cleanup can be performed in this
                            block.

                        kSecTransformActionExternalizeExtraData
                            An ExternalizeExtraData block is called before a
                            transform is externalized. If there is any extra
                            work that the transform needs to do (e.g. copy data
                            from local variables to attributes) it can be
                            performed in this block.

    @param newAction
                    A SecTransformTransformActionBlock which implements the behavior.

    @result         A CFErrorRef if an error occured NULL otherwise.
        
*/
CF_EXPORT
CFErrorRef SecTransformSetTransformAction(SecTransformImplementationRef ref,
                                CFStringRef action, 
                                SecTransformActionBlock newAction);

/*!
 @function       SecTranformCustomGetAttribute
 
 @abstract       Allow a custom transform to get an attribute value
 
 @param ref      A SecTransformImplementationRef that is bound to an instance
 of a custom transform.
 
 @param attribute
 The name or the attribute handle of the attribute whose
 value is to be retrieved.
 
 @param type     The type of data to be retrieved for the attribute.  See the 
 discussion on SecTransformMetaAttributeType for details.
 
 @result         The value of the attribute.
 
 */
CF_EXPORT
CFTypeRef SecTranformCustomGetAttribute(SecTransformImplementationRef ref, 
                                        SecTransformStringOrAttributeRef attribute,
                                        SecTransformMetaAttributeType type) AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_8;

/*!
 @function       SecTransformCustomGetAttribute
 
 @abstract       Allow a custom transform to get an attribute value
 
 @param ref      A SecTransformImplementationRef that is bound to an instance
 of a custom transform.
 
 @param attribute
 The name or the attribute handle of the attribute whose
 value is to be retrieved.
 
 @param type     The type of data to be retrieved for the attribute.  See the 
 discussion on SecTransformMetaAttributeType for details.
 
 @result         The value of the attribute.
 
 */
CF_EXPORT
CFTypeRef SecTransformCustomGetAttribute(SecTransformImplementationRef ref, 
                                        SecTransformStringOrAttributeRef attribute,
                                        SecTransformMetaAttributeType type) __asm__("_SecTranformCustomGetAttribute");

/*!
    @function       SecTransformCustomSetAttribute

    @abstract       Allow a custom transform to set an attribute value

    @param ref      A SecTransformImplementationRef that is bound to an instance
                    of a custom transform.

    @param attribute
                    The name or the attribute handle of the attribute whose
                    value is to be set.

    @param type     The type of data to be retrieved for the attribute.  See the
                    discussion on SecTransformMetaAttributeType for details.

    @param value    The new value for the attribute

    @result         A CFErrorRef if an error occured , NULL otherwise.

    @discussion     Unlike the SecTransformSetAttribute API this API can set 
                    attribute values while a transform is executing.  These
                    values are limited to the custom transform instance that
                    is bound to the ref parameter.

*/
CF_EXPORT
CFTypeRef SecTransformCustomSetAttribute(SecTransformImplementationRef ref,
                                    SecTransformStringOrAttributeRef attribute,
                                    SecTransformMetaAttributeType type,
                                    CFTypeRef value);
/*!
    @function       SecTransformPushbackAttribute

    @abstract       Allows for putting a single value back for a specific
                    attribute.  This will stop the flow of data into the
                    specified attribute until any attribute is changed for the
                    transform instance bound to the ref parameter.

    @param ref      A SecTransformImplementationRef that is bound to an instance
                    of a custom transform.

    @param attribute
                    The name or the attribute handle of the attribute whose
                    value is to be pushed back.

    @param value    The value being pushed back.

    @result         A CFErrorRef if an error occured , NULL otherwise.

*/
CF_EXPORT
CFTypeRef SecTransformPushbackAttribute(SecTransformImplementationRef ref,
                                SecTransformStringOrAttributeRef attribute,
                                CFTypeRef value);

/*!
    @typedef        SecTransformCreateFP

    @abstract       A function pointer to a function that will create a
                    new instance of a custom transform.

    @param name     The name of the new custom transform. This name MUST be
                    unique.

    @param newTransform
                    The newly created transform Ref.

    @param ref      A reference that is bound to an instance of a custom
                    transform.

    @result         A SecTransformInstanceBlock that is used to create a new
                    instance of a custom transform.

    @discussion      The CreateTransform function creates a new transform. The
                    SecTransformInstanceBlock that is returned from this
                    function provides the implementation of all of the overrides
                    necessary to create the custom transform. This returned
                    SecTransformInstanceBlock is also where the "instance"
                    variables for the custom transform may be defined. See the
                    example in the header section of this file for more detail.
*/

typedef SecTransformInstanceBlock (*SecTransformCreateFP)(CFStringRef name, 
                            SecTransformRef newTransform, 
                            SecTransformImplementationRef ref);

/************** custom Transform transform override actions   **************/

/*!
    @constant  kSecTransformActionCanExecute
                Overrides the standard behavior that checks to see if all of the
                required attributes either have been set or are connected to
                another transform.  When overriding the default behavior the
                developer can decided what the necessary data is to have for a
                transform to be considered 'ready to run'.  Returning NULL means
                that the transform is ready to be run. If the transform is NOT
                ready to run then the override should return a CFErrorRef
                stipulating the error.
 */
CF_EXPORT const CFStringRef kSecTransformActionCanExecute;
/*!
    @constant  kSecTransformActionStartingExecution
                Overrides the standard behavior that occurs just before starting
                execution of a custom transform. This is typically overridden
                to allow for initialization. This is used with the
                SecTransformOverrideTransformAction block.
 */
CF_EXPORT const CFStringRef kSecTransformActionStartingExecution;

/*!
    @constant kSecTransformActionFinalize
                Overrides the standard behavior that occurs just before deleting
                a custom transform. This is typically overridden to allow for
                memory clean up of a custom transform.  This is used with the
                SecTransformOverrideTransformAction block.
 */
CF_EXPORT const CFStringRef kSecTransformActionFinalize;

/*!

    @constant kSecTransformActionExternalizeExtraData
                Allows for adding to the data that is stored using an override
                to the kSecTransformActionExternalizeExtraData block. The output
                of this override is a dictionary that contains the custom
                externalized data. A common use of this override is to write out
                a version number of a custom transform.
 */
CF_EXPORT const CFStringRef kSecTransformActionExternalizeExtraData;

/*!
    @constant  kSecTransformActionProcessData
                Overrides the standard data processing for an attribute. This is
                almost exclusively used for processing the input attribute as
                the return value of their block sets the output attribute. This
                is used with the SecTransformOverrideAttributeAction block.
 */
CF_EXPORT const CFStringRef kSecTransformActionProcessData;

/*!
    @constant kSecTransformActionInternalizeExtraData
                Overrides the standard processing that occurs when externalized
                data is used to create a transform.  This is closely tied to the
                kSecTransformActionExternalizeExtraData override. The 'normal'
                attributes are read into the new transform and then this is
                called to read in the items that were written out using
                kSecTransformActionExternalizeExtraData override. A common use
                of this override would be to read in the version number of the
                externalized custom transform.
 */
CF_EXPORT const CFStringRef kSecTransformActionInternalizeExtraData;

/*!
    @constant SecTransformActionAttributeNotification
                Allows a block to be called when an attribute is set.  This
                allows for caching the value as a block variable in the instance
                block or transmogrifying the data to be set. This action is
                where a custom transform would be able to do processing outside
                of processing input to output as process data does.  One the
                data has been processed the action block can call
                SecTransformCustomSetAttribute to update and other attribute.
 */
CF_EXPORT const CFStringRef kSecTransformActionAttributeNotification;

/*!
    @constant kSecTransformActionAttributeValidation
                Allows a block to be called to validate the new value for an
                attribute.  The default is no validation and any CFTypeRef can
                be used as the new value.  The block should return NULL if the
                value is ok to set on the attribute or a CFErrorRef otherwise.

*/
CF_EXPORT const CFStringRef kSecTransformActionAttributeValidation;

/*!
    @function       SecTransformRegister

    @abstract       Register a new custom transform so that it may be used to 
                    process data

    @param uniqueName   
                    A unique name for this custom transform.  It is recommended
                    that a reverse DNS name be used for the name of your custom
                    transform

    @param createTransformFunction  
                    A SecTransformCreateFP function pointer. The function must
                    return a SecTransformInstanceBlock block that block_copy has
                    been called on before returning the block. Failure to call
                    block_copy will cause undefined behavior.

    @param error    This pointer is set if an error occurred.  This value 
                    may be NULL if you do not want an error returned.

    @result         True if the custom transform was registered false otherwise

*/
CF_EXPORT
Boolean SecTransformRegister(CFStringRef uniqueName, 
                                    SecTransformCreateFP createTransformFunction,
                                    CFErrorRef* error)
                            __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA);

/*!
     @function      SecTransformCreate

     @abstract      Creates a transform computation object.

     @param name    The type of transform to create, must have been registered
                    by SecTransformRegister, or be a system pre-defined
                    transform type.

     @param error   A pointer to a CFErrorRef.  This pointer is set if an error
                    occurred.  This value may be NULL if you do not want an
                    error returned.

     @result        A pointer to a SecTransformRef object.  This object must be
                    released with CFRelease when you are done with it.  This
                    function returns NULL if an error occurred.
 */
CF_EXPORT
SecTransformRef SecTransformCreate(CFStringRef name, CFErrorRef *error)
                            __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA);

/*!
    @Function       SecTransformNoData

    @abstract       Returns back A CFTypeRef from inside a processData
                    override that says that while no data is being returned
                    the transform is still active and awaiting data.

    @result         A 'special' value that allows that specifies that the
                    transform is still active and awaiting data.

    @discussion      The standard behavior for the ProcessData override is that
                    it will receive a CFDataRef and it processes that data and
                    returns a CFDataRef that contains the processed data. When
                    there is no more data to process the ProcessData override
                    block is called one last time with a NULL CFDataRef.  The
                    ProcessData block should/must return the NULL CFDataRef to
                    complete the processing.  This model does not work well for
                    some transforms. For example a digest transform needs to see
                    ALL of the data that is being digested before it can send
                    out the digest value.
                    
                    If a ProcessData block has no data to return, it can return
                    SecTransformNoData(), which informs the transform system
                    that there is no data to pass on to the next transform.


*/
CF_EXPORT
CFTypeRef SecTransformNoData(void);

CF_EXTERN_C_END

#endif // __BLOCKS__
#endif // _SEC_CUSTOM_TRANSFORM_H__