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