]> git.saurik.com Git - apple/security.git/blob - libsecurity_transform/lib/Digest_block.c
Security-55471.tar.gz
[apple/security.git] / libsecurity_transform / lib / Digest_block.c
1 /*
2 * Digest_block.cpp
3 * libsecurity_transform
4 *
5 * Created by JOsborne on 2/20/10.
6 * Copyright 2010 Apple. All rights reserved.
7 *
8 */
9
10 #include "Digest_block.h"
11 #include "SecCustomTransform.h"
12 #include <CommonCrypto/CommonDigest.h>
13 #include "Utilities.h"
14
15 extern const CFStringRef kSecDigestMD2, kSecDigestMD4, kSecDigestMD5, kSecDigestSHA1, kSecDigestSHA2;
16 extern const CFStringRef kSecDigestTypeAttribute, kSecDigestLengthAttribute;
17
18
19 static CFStringRef kCustomDigestTransformName = CFSTR("com.apple.security.digest");
20
21 SecTransformRef SecDigestTransformCreate_block(SecProviderRef device, CFTypeRef digestType, CFIndex digestLength, CFErrorRef* error) {
22 static dispatch_once_t inited;
23 __block CFStringRef current_algo;
24 __block CFIndex current_length;
25
26 dispatch_once(&inited, ^{
27 SecTransformRegister(kCustomDigestTransformName, ^(CFStringRef name, SecTransformRebindActionBlock rebind) {
28 rebind(kSecTransformActionProcessData, NULL, ^(SecTransformRef tr, CFDataRef d, SecTransformSendAttribute set) {
29 set(kSecDigestTypeAttribute, kSecDigestSHA2);
30 });
31 rebind(SecTransformSetAttributeAction, NULL, ^(SecTransformRef tr, CFStringRef name, CFTypeRef value, SecTransformSendAttribute set) {
32 Boolean algo_changed = FALSE;
33 if (name == kSecDigestTypeAttribute || CFStringCompare(kSecDigestTypeAttribute, name, 0) == kCFCompareEqualTo) {
34 algo_changed = TRUE;
35 current_algo = CFStringCreateCopy(NULL, (CFStringRef)value);
36
37 } else if (name == kSecDigestLengthAttribute || CFStringCompare(kSecDigestLengthAttribute, name, 0) == kCFCompareEqualTo) {
38 algo_changed = TRUE;
39 CFNumberGetValue(value, kCFNumberCFIndexType, &current_length);
40 } else if (CFStringCompare(kSecTransformInputAttributeName, name, 0) == kCFCompareEqualTo) {
41 return (CFTypeRef)CreateSecTransformErrorRef(kSecTransformErrorInvalidType, "The type %@ is invalid.", name);
42 } else {
43 return (CFTypeRef)CreateSecTransformErrorRef(kSecTransformErrorInvalidType, "The type %@ is invalid.", name);
44 }
45 if (!algo_changed) {
46 return value;
47 }
48
49 if (current_algo == kSecDigestSHA2 || CFStringCompare(current_algo, kSecDigestSHA2, 0) == kCFCompareEqualTo) {
50 switch (current_length) {
51 case 0:
52 case 512: {
53 __block CC_SHA512_CTX cc_context;
54 CC_SHA512_Init(&cc_context);
55 rebind(kSecTransformActionProcessData, NULL, ^(SecTransformRef tr, CFDataRef d, SecTransformSendAttribute set) {
56 if (d) {
57 CC_SHA512_Update(&cc_context, CFDataGetBytePtr(d), CFDataGetLength(d));
58 return SecTransformNoData();
59 } else {
60 u_int8_t digest_buffer[CC_SHA512_DIGEST_LENGTH];
61
62 CC_SHA512_Final(digest_buffer, &cc_context);
63 set(kSecTransformOutputAttributeName, CFDataCreate(NULL, digest_buffer, CC_SHA512_DIGEST_LENGTH));
64 return NULL;
65 }
66 });
67 return value;
68 }
69 }
70 return (CFTypeRef)CreateSecTransformErrorRef(kSecTransformErrorInvalidLength, "Invalid length.");
71 } else {
72 return (CFTypeRef)CreateSecTransformErrorRef(kSecTransformErrorInvalidAlgorithm, "Invalid algorithm.");
73 }
74 });
75 }, NULL);
76 });
77
78 SecTransformRef dt = SecTransformCreate(kCustomDigestTransformName, NULL);
79 SecTransformSetAttribute(dt, kSecDigestTypeAttribute, digestType, error);
80 CFNumberRef dlen = CFNumberCreate(NULL, kCFNumberCFIndexType, &digestLength);
81 SecTransformSetAttribute(dt, kSecDigestLengthAttribute, dlen, error);
82 CFRelease(dlen);
83
84 return dt;
85 }