]> git.saurik.com Git - apple/security.git/blob - libsecurity_transform/100-sha2.m
Security-55471.tar.gz
[apple/security.git] / libsecurity_transform / 100-sha2.m
1 /*
2 * 100-sha2.c
3 * libsecurity_transform
4 *
5 * Created by JOsborne on 2/20/10.
6 * Copyright 2010 Apple. All rights reserved.
7 *
8 */
9
10
11 #include "SecTransform.h"
12 #include "SecCustomTransform.h"
13 #include "SecDigestTransform.h"
14 #include <assert.h>
15 #include <unistd.h>
16
17 const CFStringRef kCaesarCipher = CFSTR("com.yourcompany.caesarcipher");
18 const CFStringRef kKeyAttributeName = CFSTR("key");
19
20 // =========================================================================
21 // Registration function for a ROT-N (caesar cipher)
22 // =========================================================================
23 Boolean RegisterMyCustomTransform()
24 {
25 static dispatch_once_t once;
26 __block Boolean ok = FALSE;
27 __block CFErrorRef error = NULL;
28
29 SecTransformCreateBlock createCaesar = NULL;
30
31 // Create the SecTransformCreateBlock block that will be used to
32 // register this custom transform
33 createCaesar =^(CFStringRef name, SecTransformRef new_transform,
34 const SecTransformCreateBlockParameters* parameters)
35 {
36
37 CFErrorRef result = NULL;
38
39 // Some basic parameter checking.
40 if (NULL == name || NULL == new_transform )
41 {
42 // return the error
43 result = CFErrorCreate(kCFAllocatorDefault, SECTRANSFORM_ERROR_DOMAIN,
44 kSecTransformErrorInvalidInput, NULL);
45
46 return result;
47 }
48 // Every time a new instance of this custom transform class is
49 // created, this block will be called. This behavior means that any
50 // block variables created in this block will act like instance
51 // variables for the new custom transform instance. In this case
52 // the key variable will be in every instance of this custom
53 // caesar transform
54
55 __block int _key;
56
57 // Use the overrideAttribute block to have our custom transform
58 // be notified if the 'key' attribute is set
59
60 parameters->overrideAttribute(
61 kSecCustomTransformAttributeSetNotification,
62 kKeyAttributeName,
63 ^(SecTransformAttributeRef name, CFTypeRef d)
64 {
65 CFTypeRef result = NULL;
66
67 if (NULL == d)
68 {
69 _key = 0;
70 return result;
71 }
72
73 // Ensure the correct data type for this attribute
74 if (CFGetTypeID(d) == CFNumberGetTypeID())
75 {
76 _key = 0;
77
78 if (!CFNumberGetValue((CFNumberRef)d,
79 kCFNumberIntType, &_key))
80 {
81 _key = 0;
82 // return the error
83 result = (CFTypeRef)CFErrorCreate(kCFAllocatorDefault, SECTRANSFORM_ERROR_DOMAIN,
84 kSecTransformErrorInvalidInput, NULL);
85
86 return result;
87 }
88 else
89 {
90 result = d;
91 }
92 }
93
94 return result;
95
96 });
97
98 // Use the overrideAttribute to change the processing of the data
99 // for this transform
100 parameters->overrideAttribute(kSecCustomTransformProcessData,
101 NULL,
102 ^(SecTransformAttributeRef name, CFTypeRef d)
103 {
104 CFTypeRef result = NULL;
105 if (NULL == d)
106 {
107 // return the error
108 result = (CFTypeRef)CFErrorCreate(kCFAllocatorDefault, SECTRANSFORM_ERROR_DOMAIN,
109 kSecTransformErrorInvalidInput, NULL);
110
111 return result;
112 }
113
114 if (CFGetTypeID(d) != CFDataGetTypeID())
115 {
116 // return the error
117 result = (CFTypeRef)CFErrorCreate(kCFAllocatorDefault, SECTRANSFORM_ERROR_DOMAIN,
118 kSecTransformErrorInvalidInput, NULL);
119
120 return result;
121 }
122
123 CFDataRef theData = (CFDataRef)d;
124
125 CFIndex dataLength = CFDataGetLength(theData);
126
127 // Do the processing in memory. There are better ways to do
128 // this but for showing how custom transforms work this is fine.
129 char* buffer = (char*)malloc(dataLength);
130 if (NULL == buffer)
131 {
132 //return the error
133 result = (CFErrorRef)CFErrorCreate(kCFAllocatorDefault, SECTRANSFORM_ERROR_DOMAIN,
134 kSecTransformErrorInvalidInput, NULL);
135
136 return result;
137 }
138
139 const char* dataPtr = (const char* )CFDataGetBytePtr(theData);
140 if (NULL == dataPtr)
141 {
142 free(buffer);
143 //return the error
144 result = (CFErrorRef)CFErrorCreate(kCFAllocatorDefault, SECTRANSFORM_ERROR_DOMAIN,
145 kSecTransformErrorInvalidInput, NULL);
146
147 return result;
148 }
149 // Do the work of the caesar cipher (Rot(n))
150
151 char rotValue = (char)_key;
152 CFIndex iCnt;
153 for (iCnt = 0; iCnt < dataLength; iCnt++)
154 {
155 buffer[iCnt] = dataPtr[iCnt] + rotValue;
156 }
157
158 result = (CFTypeRef)CFDataCreate(kCFAllocatorDefault,
159 (const UInt8 *)buffer, dataLength);
160 free(buffer);
161 return result;
162
163 });
164 };
165
166 // Make sure the custom transform is only registered once
167 dispatch_once(&once,
168 ^{
169 (void)SecCustomTransformRegister(kCaesarCipher, &error,
170 createCaesar);
171 });
172
173 return (error == NULL);
174 }
175
176 //The second function show how to use the this custom transform:
177
178 // =========================================================================
179 // Use a custom ROT-N (caesar cipher) transform
180 // =========================================================================
181 CFStringRef DoCaesar(CFStringRef clearTest, int rotNumber)
182 {
183 CFStringRef result = NULL;
184
185 if (NULL == clearTest)
186 {
187 return result;
188 }
189
190 if (!RegisterMyCustomTransform())
191 {
192 return result;
193 }
194
195 CFErrorRef error = NULL;
196
197 SecTransformRef caesarCipher =
198 SecCustomTransformCreate(kCaesarCipher, &error);
199 if (NULL == caesarCipher || NULL != error)
200 {
201 return result;
202 }
203
204 CFDataRef data =
205 CFStringCreateExternalRepresentation(kCFAllocatorDefault,
206 clearTest, kCFStringEncodingUTF8, 0);
207 if (NULL == data)
208 {
209 CFRelease(caesarCipher);
210 return result;
211 }
212
213 SecTransformSetAttribute(caesarCipher,
214 kSecTransformInputAttributeName, data, &error);
215 CFRelease(data);
216 if (NULL != error)
217 {
218 CFRelease(caesarCipher);
219 return result;
220 }
221
222 CFNumberRef keyNumber =
223 CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &rotNumber);
224 if (NULL == keyNumber)
225 {
226 CFRelease(caesarCipher);
227 return result;
228 }
229
230 SecTransformSetAttribute(caesarCipher, kKeyAttributeName,
231 keyNumber, &error);
232 CFRelease(keyNumber);
233 if (NULL != error)
234 {
235 CFRelease(caesarCipher);
236 return result;
237 }
238
239 CFDataRef dataResult =
240 (CFDataRef)SecTransformExecute(caesarCipher, &error);
241 CFRelease(caesarCipher);
242 if (NULL != dataResult && NULL == error)
243 {
244 result =
245 CFStringCreateFromExternalRepresentation(kCFAllocatorDefault,
246 dataResult, kCFStringEncodingUTF8);
247 CFRelease(dataResult);
248 }
249
250 return result;
251 }
252
253 int main(int argc, char *argv[])
254 {
255 if (!RegisterMyCustomTransform())
256 {
257 return -1;
258 }
259
260 CFStringRef testStr = CFSTR("When in the course of human event");
261 CFStringRef aStr = DoCaesar(testStr, 4);
262 CFStringRef clearStr = DoCaesar(aStr, -4);
263 if (CFEqual(testStr, clearStr))
264 {
265 CFShow(CFSTR("All is right with the world"));
266 return 0;
267 }
268
269 CFShow(CFSTR("Bummer!"));
270 return -1;
271
272 }
273
274
275
276 /*
277 CFReadStreamRef CFReadStreamCreateWithFD(CFAllocatorRef a, int fd) {
278 char *fname;
279 asprintf(&fname, "/dev/fd/%d", fd);
280 CFURLRef f = CFURLCreateFromFileSystemRepresentation(a, (UInt8*)fname, strlen(fname), FALSE);
281 CFReadStreamRef rd = CFReadStreamCreateWithFile(a, f);
282 CFRelease(f);
283
284 return rd;
285 }
286
287 void pair_CFReadStream_fd(CFReadStreamRef *sr, int *fd) {
288 int fds[2];
289 int rc = pipe(fds);
290 assert(rc >= 0);
291 *fd = fds[1];
292 *sr = CFReadStreamCreateWithFD(NULL, fds[0]);
293 }
294
295 CFReadStreamRef many_zeros(uint64_t goal) {
296 CFReadStreamRef rd;
297 int fd;
298 pair_CFReadStream_fd(&rd, &fd);
299
300 // XXX: replace with a dispatch_source and non-blocking I/O...
301 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
302 uint64_t nwrites = 0;
303 char buf[1024*8];
304 bzero(buf, sizeof(buf));
305 uint64_t left = goal;
306
307 while (left) {
308 size_t try = (sizeof(buf) < left) ? sizeof(buf) : left;
309 ssize_t sz = write(fd, buf, try);
310 if (sz <= 0) {
311 fprintf(stderr, "Write return %zd, errno=%d\n", sz, errno);
312 }
313 assert(sz >= 0);
314 left -= sz;
315 nwrites++;
316 }
317
318 close(fd);
319 });
320
321
322 return rd;
323 }
324
325 int main(int argc, char *argv[]) {
326 CFReadStreamRef rd = many_zeros(1024*1024 *100LL);
327 Boolean ok = CFReadStreamOpen(rd);
328 assert(ok);
329
330 SecTransformRef dt = SecDigestTransformCreate(kSecDigestSHA2, 512, NULL);
331 SecTransformSetAttribute(dt, kSecTransformInputAttributeName, rd, NULL);
332
333 CFDataRef d = SecTransformExecute(dt, NULL);
334
335 return 0;
336 }
337 */