]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_transform/100-sha2.m
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_transform / 100-sha2.m
diff --git a/Security/libsecurity_transform/100-sha2.m b/Security/libsecurity_transform/100-sha2.m
new file mode 100644 (file)
index 0000000..ec9d3c9
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2010-2011,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 "SecTransform.h"
+#include "SecCustomTransform.h"
+#include "SecDigestTransform.h"
+#include <assert.h>
+#include <unistd.h>
+
+const CFStringRef kCaesarCipher = CFSTR("com.yourcompany.caesarcipher");
+const CFStringRef kKeyAttributeName = CFSTR("key");
+
+// =========================================================================
+//     Registration function for a ROT-N (caesar cipher)
+// =========================================================================
+Boolean RegisterMyCustomTransform()
+{
+       static dispatch_once_t once;
+       __block Boolean ok = FALSE;
+       __block CFErrorRef error = NULL;
+       
+       SecTransformCreateBlock createCaesar = NULL;
+       
+       // Create the SecTransformCreateBlock block that will be used to 
+       // register this custom transform
+       createCaesar =^(CFStringRef name, SecTransformRef new_transform, 
+                                       const SecTransformCreateBlockParameters* parameters) 
+       {
+               
+               CFErrorRef result = NULL;
+               
+               // Some basic parameter checking.
+               if (NULL == name || NULL == new_transform )
+               {
+                       // return the error
+                       result = CFErrorCreate(kCFAllocatorDefault, SECTRANSFORM_ERROR_DOMAIN, 
+                                                                  kSecTransformErrorInvalidInput, NULL);
+                       
+                       return result;
+               }
+               // Every time a new instance of this custom transform class is 
+               // created, this block will be called. This behavior means that any 
+               // block variables created in this block will act like instance
+               // variables for the new custom transform instance.  In this case 
+               // the key variable will be in every instance of this custom 
+               // caesar transform
+               
+               __block int _key;
+               
+               // Use the overrideAttribute block to have our custom transform 
+               // be notified if the 'key' attribute is set
+               
+               parameters->overrideAttribute(
+                 kSecCustomTransformAttributeSetNotification, 
+                 kKeyAttributeName,
+                 ^(SecTransformAttributeRef name, CFTypeRef d)
+                 {
+                         CFTypeRef result = NULL;
+                         
+                         if (NULL == d)
+                         {
+                                 _key = 0;
+                                 return result;
+                         }
+                         
+                         // Ensure the correct data type for this attribute
+                         if (CFGetTypeID(d) == CFNumberGetTypeID())
+                         {
+                                 _key = 0;
+                                 
+                                 if (!CFNumberGetValue((CFNumberRef)d, 
+                                                                               kCFNumberIntType, &_key))
+                                 {
+                                         _key = 0;
+                                         // return the error
+                                         result = (CFTypeRef)CFErrorCreate(kCFAllocatorDefault, SECTRANSFORM_ERROR_DOMAIN, 
+                                                                                                               kSecTransformErrorInvalidInput, NULL);
+                                         
+                                         return result;                                                        
+                                 }
+                                 else 
+                                 {
+                                         result = d;
+                                 }
+                         }
+                         
+                         return result;
+                         
+                 });
+               
+               // Use the overrideAttribute to change the processing of the data 
+               // for this transform
+               parameters->overrideAttribute(kSecCustomTransformProcessData, 
+                 NULL, 
+                 ^(SecTransformAttributeRef name, CFTypeRef d)
+                 {
+                         CFTypeRef result = NULL;
+                         if (NULL == d)
+                         {
+                                 // return the error
+                                 result = (CFTypeRef)CFErrorCreate(kCFAllocatorDefault, SECTRANSFORM_ERROR_DOMAIN, 
+                                                                                                       kSecTransformErrorInvalidInput, NULL);
+                                 
+                                 return result;
+                         }
+                         
+                         if (CFGetTypeID(d) != CFDataGetTypeID())
+                         {
+                                 // return the error
+                                 result = (CFTypeRef)CFErrorCreate(kCFAllocatorDefault, SECTRANSFORM_ERROR_DOMAIN, 
+                                                                                                       kSecTransformErrorInvalidInput, NULL);
+                                 
+                                 return result;
+                         }
+                         
+                         CFDataRef theData = (CFDataRef)d;
+                         
+                         CFIndex dataLength = CFDataGetLength(theData);
+                         
+                         // 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 the error
+                                 result = (CFErrorRef)CFErrorCreate(kCFAllocatorDefault, SECTRANSFORM_ERROR_DOMAIN, 
+                                                                                                        kSecTransformErrorInvalidInput, NULL);
+                                 
+                                 return result;
+                         }
+                         
+                         const char* dataPtr = (const char* )CFDataGetBytePtr(theData);
+                         if (NULL == dataPtr)
+                         {
+                                 free(buffer);
+                                 //return the error
+                                 result = (CFErrorRef)CFErrorCreate(kCFAllocatorDefault, SECTRANSFORM_ERROR_DOMAIN, 
+                                                                                                        kSecTransformErrorInvalidInput, NULL);
+                                 
+                                 return result;
+                         }
+                         // Do the work of the caesar cipher (Rot(n))
+                         
+                         char rotValue = (char)_key;
+                         CFIndex iCnt;
+                         for (iCnt = 0; iCnt < dataLength; iCnt++)
+                         {
+                                 buffer[iCnt] = dataPtr[iCnt] + rotValue;
+                         }
+                         
+                         result = (CFTypeRef)CFDataCreate(kCFAllocatorDefault, 
+                                                                                          (const UInt8 *)buffer, dataLength);
+                         free(buffer);
+                         return result;
+                         
+                 });
+       };
+       
+       // Make sure the custom transform is only registered once       
+       dispatch_once(&once, 
+                                 ^{ 
+                                         (void)SecCustomTransformRegister(kCaesarCipher, &error, 
+                                                                                                          createCaesar);
+                                 });
+       
+       return (error == NULL);
+} 
+
+//The second function show how to use the this custom transform:
+
+// =========================================================================
+//     Use a custom ROT-N (caesar cipher) transform
+// =========================================================================
+CFStringRef DoCaesar(CFStringRef clearTest, int rotNumber)
+{
+       CFStringRef result = NULL;
+       
+       if (NULL == clearTest)
+       {
+               return result;
+       }
+       
+       if (!RegisterMyCustomTransform())
+       {
+               return result;
+       }
+       
+       CFErrorRef error = NULL;
+       
+       SecTransformRef caesarCipher = 
+       SecCustomTransformCreate(kCaesarCipher, &error);
+       if (NULL == caesarCipher || NULL != error)
+       {
+               return result;
+       }
+       
+       CFDataRef  data = 
+       CFStringCreateExternalRepresentation(kCFAllocatorDefault, 
+                                                                                clearTest, kCFStringEncodingUTF8, 0);
+       if (NULL == data)               
+       {
+               CFRelease(caesarCipher);
+               return result;
+       }
+       
+       SecTransformSetAttribute(caesarCipher, 
+                                                        kSecTransformInputAttributeName, data, &error);
+       CFRelease(data);
+       if (NULL != error)
+       {
+               CFRelease(caesarCipher);
+               return result;
+       }
+       
+       CFNumberRef keyNumber = 
+       CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &rotNumber);
+       if (NULL == keyNumber)
+       {
+               CFRelease(caesarCipher);
+               return result;
+       }
+       
+       SecTransformSetAttribute(caesarCipher, kKeyAttributeName, 
+                                                        keyNumber, &error);
+       CFRelease(keyNumber);
+       if (NULL != error)
+       {
+               CFRelease(caesarCipher);
+               return result;
+       }
+       
+       CFDataRef dataResult = 
+       (CFDataRef)SecTransformExecute(caesarCipher, &error);
+       CFRelease(caesarCipher);
+       if (NULL != dataResult && NULL == error)
+       {
+               result = 
+               CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, 
+                                                                                                dataResult, kCFStringEncodingUTF8);    
+               CFRelease(dataResult);
+       }
+       
+       return result;
+}
+
+int main(int argc, char *argv[]) 
+{
+       if (!RegisterMyCustomTransform())
+       {
+               return -1;
+       }
+       
+       CFStringRef testStr = CFSTR("When in the course of human event");
+       CFStringRef aStr = DoCaesar(testStr, 4);
+       CFStringRef clearStr = DoCaesar(aStr, -4);
+       if (CFEqual(testStr, clearStr))
+       {
+               CFShow(CFSTR("All is right with the world"));
+               return 0;
+       }
+       
+       CFShow(CFSTR("Bummer!"));
+       return -1;
+       
+}
+
+
+
+/*
+CFReadStreamRef CFReadStreamCreateWithFD(CFAllocatorRef a, int fd) {
+       char *fname;
+       asprintf(&fname, "/dev/fd/%d", fd);
+       CFURLRef f = CFURLCreateFromFileSystemRepresentation(a, (UInt8*)fname, strlen(fname), FALSE);
+       CFReadStreamRef rd = CFReadStreamCreateWithFile(a, f);
+       CFRelease(f);
+       
+       return rd;
+}
+
+void pair_CFReadStream_fd(CFReadStreamRef *sr, int *fd) {
+       int fds[2];
+       int rc = pipe(fds);
+       assert(rc >= 0);
+       *fd = fds[1];
+       *sr = CFReadStreamCreateWithFD(NULL, fds[0]);
+}
+
+CFReadStreamRef many_zeros(uint64_t goal) {
+       CFReadStreamRef rd;
+       int fd;
+       pair_CFReadStream_fd(&rd, &fd);
+       
+       // XXX: replace with a dispatch_source and non-blocking I/O...
+       dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
+               uint64_t nwrites = 0;
+               char buf[1024*8];
+               bzero(buf, sizeof(buf));
+               uint64_t left = goal;
+               
+               while (left) {
+                       size_t try = (sizeof(buf) < left) ? sizeof(buf) : left;
+                       ssize_t sz = write(fd, buf, try);
+                       if (sz <= 0) {
+                               fprintf(stderr, "Write return %zd, errno=%d\n", sz, errno);
+                       }
+                       assert(sz >= 0);
+                       left -= sz;
+                       nwrites++;
+               }
+               
+               close(fd);
+       });
+       
+       
+       return rd;
+}
+
+int main(int argc, char *argv[]) {
+       CFReadStreamRef rd = many_zeros(1024*1024 *100LL);
+       Boolean ok = CFReadStreamOpen(rd);
+       assert(ok);
+       
+       SecTransformRef dt = SecDigestTransformCreate(kSecDigestSHA2, 512, NULL);
+       SecTransformSetAttribute(dt, kSecTransformInputAttributeName, rd, NULL);
+       
+       CFDataRef d = SecTransformExecute(dt, NULL);
+       
+       return 0;
+}
+*/