/* * Copyright (c) 2010-2012 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@ */ #ifndef _SEC_TRANSFORM_H__ #define _SEC_TRANSFORM_H__ #include CF_EXTERN_C_BEGIN CF_ASSUME_NONNULL_BEGIN CF_IMPLICIT_BRIDGING_ENABLED /*! @header To better follow this header, you should understand the following terms: Transform A transform converts data from one form to another. Digests, encryption and decryption are all examples of transforms. Each transform performs a single operation. Transform Group A transform group is a directed (typically) acyclic graph of transforms. Results from a transform flow to the next Transform in the graph, and so on until the end of the graph is reached. Attribute Transforms may have one or more attributes. These attributes are parameters for the transforms and may affect the operation of the transform. The value of an attribute may be set with static data or from the value of an attribute in another transform by connecting the attributes using the SecTransformConnectTransforms API. External Representation Transforms may be created programmatically or from an external representation. External representations may be created from existing transforms. There are many types of transforms available. These are documented in their own headers. The functions in this header are applicable to all transforms. */ /*! @constant kSecTransformErrorDomain The domain for CFErrorRefs created by Transforms */ CF_EXPORT const CFStringRef kSecTransformErrorDomain; /*! @constant kSecTransformPreviousErrorKey If multiple errors occurred, the CFErrorRef that is returned from a Transfo]rm API will have a userInfo dictionary and that dictionary will have the previous error keyed by the kSecTransformPreviousErrorKey. */ CF_EXPORT const CFStringRef kSecTransformPreviousErrorKey; /*! @constant kSecTransformAbortOriginatorKey The value of this key will be the transform that caused the transform chain to abort. */ CF_EXPORT const CFStringRef kSecTransformAbortOriginatorKey; /**************** Transform Error Codes ****************/ /*! @enum Security Transform Error Codes @discussion @const kSecTransformErrorAttributeNotFound The attribute was not found. @const kSecTransformErrorInvalidOperation An invalid operation was attempted. @const kSecTransformErrorNotInitializedCorrectly A required initialization is missing. It is most likely a missing required attribute. @const kSecTransformErrorMoreThanOneOutput A transform has an internal routing error that has caused multiple outputs instead of a single discrete output. This will occur if SecTransformExecute has already been called. @const kSecTransformErrorInvalidInputDictionary A dictionary given to SecTransformCreateFromExternalRepresentation has invalid data. @const kSecTransformErrorInvalidAlgorithm A transform that needs an algorithm as an attribute i.e the Sign and Verify transforms, received an invalid algorithm. @const kSecTransformErrorInvalidLength A transform that needs a length such as a digest transform has been given an invalid length. @const kSecTransformErrorInvalidType An invalid type has been set on an attribute. @const kSecTransformErrorInvalidInput The input set on a transform is invalid. This can occur if the data set for an attribute does not meet certain requirements such as correct key usage for signing data. @const kSecTransformErrorNameAlreadyRegistered A custom transform of a particular name has already been registered. @const kSecTransformErrorUnsupportedAttribute An illegal action such as setting a read only attribute has occurred. @const kSecTransformOperationNotSupportedOnGroup An illegal action on a group transform such as trying to call SecTransformSetAttribute has occurred. @const kSecTransformErrorMissingParameter A transform is missing a required attribute. @const kSecTransformErrorInvalidConnection A SecTransformConnectTransforms was called with transforms in different groups. @const kSecTransformTransformIsExecuting An illegal operation was called on a Transform while it was executing. Please see the sequencing documentation in the discussion area of the SecTransformExecute API @const kSecTransformInvalidOverride An illegal override was given to a custom transform @const kSecTransformTransformIsNotRegistered A custom transform was asked to be created but the transform has not been registered. @const kSecTransformErrorAbortInProgress The abort attribute has been set and the transform is in the process of shutting down @const kSecTransformErrorAborted The transform was aborted. @const kSecTransformInvalidArgument An invalid argument was given to a Transform API */ CF_ENUM(CFIndex) { kSecTransformErrorAttributeNotFound = 1, kSecTransformErrorInvalidOperation = 2, kSecTransformErrorNotInitializedCorrectly = 3, kSecTransformErrorMoreThanOneOutput = 4, kSecTransformErrorInvalidInputDictionary = 5, kSecTransformErrorInvalidAlgorithm = 6, kSecTransformErrorInvalidLength = 7, kSecTransformErrorInvalidType = 8, kSecTransformErrorInvalidInput = 10, kSecTransformErrorNameAlreadyRegistered = 11, kSecTransformErrorUnsupportedAttribute = 12, kSecTransformOperationNotSupportedOnGroup = 13, kSecTransformErrorMissingParameter = 14, kSecTransformErrorInvalidConnection = 15, kSecTransformTransformIsExecuting = 16, kSecTransformInvalidOverride = 17, kSecTransformTransformIsNotRegistered = 18, kSecTransformErrorAbortInProgress = 19, kSecTransformErrorAborted = 20, kSecTransformInvalidArgument = 21 }; typedef CFTypeRef SecTransformRef; typedef CFTypeRef SecGroupTransformRef; /*! @function SecTransformGetTypeID @abstract Return the CFTypeID for a SecTransform. @result The CFTypeID */ CF_EXPORT CFTypeID SecTransformGetTypeID(void); /*! @function SecGroupTransformGetTypeID @abstract Return the CFTypeID for a SecTransformGroup. @result The CFTypeID */ CF_EXPORT CFTypeID SecGroupTransformGetTypeID(void); /**************** Transform Attribute Names ****************/ /*! @constant kSecTransformInputAttributeName The name of the input attribute. */ CF_EXPORT const CFStringRef kSecTransformInputAttributeName __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA); /*! @constant kSecTransformOutputAttributeName The name of the output attribute. */ CF_EXPORT const CFStringRef kSecTransformOutputAttributeName __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA); /*! @constant kSecTransformDebugAttributeName Set this attribute to a CFWriteStream. This will signal the transform to write debugging information to the stream. If this attribute is set to kCFBooleanTrue then the debugging data will be written out to stderr. */ CF_EXPORT const CFStringRef kSecTransformDebugAttributeName __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA); /*! @constant kSecTransformTransformName The name of the transform. */ CF_EXPORT const CFStringRef kSecTransformTransformName __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA); /*! @constant kSecTransformAbortAttributeName The name of the abort attribute. */ CF_EXPORT const CFStringRef kSecTransformAbortAttributeName __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA); /*! @function SecTransformCreateFromExternalRepresentation @abstract Creates a transform instance from a CFDictionary of parameters. @param dictionary The dictionary of parameters. @param error An optional pointer to a CFErrorRef. This value is set if an error occurred. If not NULL the caller is responsible for releasing the CFErrorRef. @result A pointer to a SecTransformRef object. You must release the object with CFRelease when you are done with it. A NULL will be returned if an error occurred during initialization, and if the error parameter is non-null, it contains the specific error data. */ CF_EXPORT __nullable SecTransformRef SecTransformCreateFromExternalRepresentation( CFDictionaryRef dictionary, CFErrorRef *error) __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA); /*! @function SecTransformCopyExternalRepresentation @abstract Create a CFDictionaryRef that contains enough information to be able to recreate a transform. @param transformRef The transformRef to be externalized. @discussion This function returns a CFDictionaryRef that contains sufficient information to be able to recreate this transform. You can pass this CFDictionaryRef to SecTransformCreateFromExternalRepresentation to be able to recreate the transform. The dictionary can also be written out to disk using the techniques described here. http://developer.apple.com/mac/library/documentation/CoreFoundation/Conceptual/CFPropertyLists/Articles/Saving.html */ CF_EXPORT CFDictionaryRef SecTransformCopyExternalRepresentation( SecTransformRef transformRef) __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA); /*! @function SecTransformCreateGroupTransform @abstract Create a SecGroupTransformRef that acts as a container for a set of connected transforms. @result A reference to a SecGroupTransform. @discussion A SecGroupTransformRef is a container for all of the transforms that are in a directed graph. A SecGroupTransformRef can be used with SecTransformExecute, SecTransformExecuteAsync and SecTransformCopyExternalRepresentation APIs. While the intention is that a SecGroupTransformRef willwork just like a S SecTransformRef that is currently not the case. Using a SecGroupTransformRef with the SecTransformConnectTransforms, SecTransformSetAttribute and SecTransformGetAttribute is undefined. */ CF_EXPORT SecGroupTransformRef SecTransformCreateGroupTransform(void); /*! @function SecTransformConnectTransforms @abstract Pipe fitting for transforms. @param sourceTransformRef The transform that sends the data to the destinationTransformRef. @param sourceAttributeName The name of the attribute in the sourceTransformRef that supplies the data to the destinationTransformRef. Any attribute of the transform may be used as a source. @param destinationTransformRef The transform that has one of its attributes be set with the data from the sourceTransformRef parameter. @param destinationAttributeName The name of the attribute within the destinationTransformRef whose data is set with the data from the sourceTransformRef sourceAttributeName attribute. Any attribute of the transform may be set. @param group In order to ensure referential integrity, transforms are chained together into a directed graph and placed into a group. Each transform that makes up the graph must be placed into the same group. After a SecTransformRef has been placed into a group by calling the SecTransformConnectTransforms it may be released as the group will retain the transform. CFRelease the group after you execute it, or when you determine you will never execute it. In the example below, the output of trans1 is set to be the input of trans2. The output of trans2 is set to be the input of trans3. Since the same group was used for the connections, the three transforms are in the same group.
@textblock
						SecGroupTransformRef group =SecTransformCreateGroupTransform();
						CFErrorRef error = NULL;
						
						SecTransformRef trans1; // previously created using a 
												// Transform construction API
												// like SecEncryptTransformCreate
												
						SecTransformRef trans2;	// previously created using a 
												// Transform construction API
												// like SecEncryptTransformCreate
					
						SecTransformRef trans3; // previously created using a 
												// Transform construction API
												// like SecEncryptTransformCreate
						
						
						SecTransformConnectTransforms(trans1, kSecTransformOutputAttributeName,
													  trans2, kSecTransformInputAttributeName,
													  group, &error);
						
						SecTransformConnectTransforms(trans2, kSecTransformOutputAttributeName,
													  trans3, kSecTransformInputAttributeName.
													  group, &error);
						CFRelease(trans1);
						CFRelease(trans2);
						CFRelease(trans3);
						
						CFDataRef = (CFDataRef)SecTransformExecute(group, &error, NULL, NULL);
						CFRelease(group);					
@/textblock
@param error An optional pointer to a CFErrorRef. This value is set if an error occurred. If not NULL, the caller is responsible for releasing the CFErrorRef. @result The value returned is SecGroupTransformRef parameter. This will allow for chaining calls to SecTransformConnectTransforms. @discussion This function places transforms into a group by attaching the value of an attribute of one transform to the attribute of another transform. Typically the attribute supplying the data is the kSecTransformAttrOutput attribute but that is not a requirement. It can be used to set an attribute like Salt with the output attribute of a random number transform. This function returns an error and the named attribute will not be changed if SecTransformExecute had previously been called on the transform. */ CF_EXPORT __nullable SecGroupTransformRef SecTransformConnectTransforms(SecTransformRef sourceTransformRef, CFStringRef sourceAttributeName, SecTransformRef destinationTransformRef, CFStringRef destinationAttributeName, SecGroupTransformRef group, CFErrorRef *error) __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA); /*! @function SecTransformSetAttribute @abstract Set a static value as the value of an attribute in a transform. This is useful for things like iteration counts and other non-changing values. @param transformRef The transform whose attribute is to be set. @param key The name of the attribute to be set. @param value The static value to set for the named attribute. @param error An optional pointer to a CFErrorRef. This value is set if an error occurred. If not NULL the caller is responsible for releasing the CFErrorRef. @result Returns true if the call succeeded. If an error occurred, the error parameter has more information about the failure case. @discussion This API allows for setting static data into an attribute for a transform. This is in contrast to the SecTransformConnectTransforms function which sets derived data. This function will return an error and the named attribute will not be changed if SecTransformExecute has been called on the transform. */ CF_EXPORT Boolean SecTransformSetAttribute(SecTransformRef transformRef, CFStringRef key, CFTypeRef value, CFErrorRef *error) __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA); /*! @function SecTransformGetAttribute @abstract Get the current value of a transform attribute. @param transformRef The transform whose attribute value will be retrieved. @param key The name of the attribute to retrieve. @result The value of an attribute. If this attribute is being set as the output of another transform and SecTransformExecute has not been called on the transform or if the attribute does not exists then NULL will be returned. @discussion This may be called after SecTransformExecute. */ CF_EXPORT __nullable CFTypeRef SecTransformGetAttribute(SecTransformRef transformRef, CFStringRef key) __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA); /*! @function SecTransformFindByName @abstract Finds a member of a transform group by its name. @param transform The transform group to be searched. @param name The name of the transform to be found. @discussion When a transform instance is created it will be given a unique name. This name can be used to find that instance in a group. While it is possible to change this unique name using the SecTransformSetAttribute API, developers should not do so. This allows SecTransformFindTransformByName to work correctly. @result The transform group member, or NULL if the member was not found. */ CF_EXPORT __nullable SecTransformRef SecTransformFindByName(SecGroupTransformRef transform, CFStringRef name) __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA); /*! @function SecTransformExecute @abstract Executes a Transform or transform group synchronously. @param transformRef The transform to execute. @param errorRef An optional pointer to a CFErrorRef. This value will be set if an error occurred during initialization or execution of the transform or group. If not NULL the caller will be responsible for releasing the returned CFErrorRef. @result This is the result of the transform. The specific value is determined by the transform being executed. @discussion There are two phases that occur when executing a transform. The first phase checks to see if the tranforms have all of their required attributes set. If a GroupTransform is being executed, then a required attribute for a transform is valid if it is connected to another attribute that supplies the required value. If any of the required attributes are not set or connected then SecTransformExecute will not run the transform but will return NULL and the apporiate error is placed in the error parameter if it is not NULL. The second phase is the actual execution of the transform. SecTransformExecute executes the transform or GroupTransform and when all of the processing is completed it returns the result. If an error occurs during execution, then all processing will stop and NULL will be returned and the appropriate error will be placed in the error parameter if it is not NULL. */ CF_EXPORT CF_RETURNS_RETAINED CFTypeRef SecTransformExecute(SecTransformRef transformRef, CFErrorRef* errorRef) __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA) CF_RETURNS_RETAINED; /*! @typedef SecMessageBlock @abstract A SecMessageBlock is used by a transform instance to deliver messages during asynchronous operations. @param message A CFType containing the message. This is where either intermediate or final results are returned. @param error If an error occurred, this will contain a CFErrorRef, otherwise this will be NULL. If not NULL the caller is responsible for releasing the CFErrorRef. @param isFinal If set the message returned is the final result otherwise it is an intermediate result. */ typedef void (^SecMessageBlock)(CFTypeRef __nullable message, CFErrorRef __nullable error, Boolean isFinal); /*! @function SecTransformExecuteAsync @abstract Executes Transform or transform group asynchronously. @param transformRef The transform to execute. @param deliveryQueue A dispatch queue on which to deliver the results of this transform. @param deliveryBlock A SecMessageBlock to asynchronously receive the results of the transform. @discussion SecTransformExecuteAsync works just like the SecTransformExecute API except that it returns results to the deliveryBlock. There may be multple results depending on the transform. The block knows that the processing is complete when the isFinal parameter is set to true. If an error occurs the block's error parameter is set and the isFinal parameter will be set to true. */ CF_EXPORT void SecTransformExecuteAsync(SecTransformRef transformRef, dispatch_queue_t deliveryQueue, SecMessageBlock deliveryBlock) __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_NA); CF_IMPLICIT_BRIDGING_DISABLED CF_ASSUME_NONNULL_END CF_EXTERN_C_END #endif /* _SEC_TRANSFORM_H__ */