3 * libsecurity_transform
5 * Created by JOsborne on 2/20/10.
6 * Copyright 2010 Apple. All rights reserved.
10 #include "Digest_block.h"
11 #include "SecCustomTransform.h"
12 #include <CommonCrypto/CommonDigest.h>
13 #include "Utilities.h"
15 extern const CFStringRef kSecDigestMD2
, kSecDigestMD4
, kSecDigestMD5
, kSecDigestSHA1
, kSecDigestSHA2
;
16 extern const CFStringRef kSecDigestTypeAttribute
, kSecDigestLengthAttribute
;
19 static CFStringRef kCustomDigestTransformName
= CFSTR("com.apple.security.digest");
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
;
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
);
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
) {
35 current_algo
= CFStringCreateCopy(NULL
, (CFStringRef
)value
);
37 } else if (name
== kSecDigestLengthAttribute
|| CFStringCompare(kSecDigestLengthAttribute
, name
, 0) == kCFCompareEqualTo
) {
39 CFNumberGetValue(value
, kCFNumberCFIndexType
, ¤t_length
);
40 } else if (CFStringCompare(kSecTransformInputAttributeName
, name
, 0) == kCFCompareEqualTo
) {
41 return (CFTypeRef
)CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "The type %@ is invalid.", name
);
43 return (CFTypeRef
)CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "The type %@ is invalid.", name
);
49 if (current_algo
== kSecDigestSHA2
|| CFStringCompare(current_algo
, kSecDigestSHA2
, 0) == kCFCompareEqualTo
) {
50 switch (current_length
) {
53 __block CC_SHA512_CTX cc_context
;
54 CC_SHA512_Init(&cc_context
);
55 rebind(kSecTransformActionProcessData
, NULL
, ^(SecTransformRef tr
, CFDataRef d
, SecTransformSendAttribute set
) {
57 CC_SHA512_Update(&cc_context
, CFDataGetBytePtr(d
), CFDataGetLength(d
));
58 return SecTransformNoData();
60 u_int8_t digest_buffer
[CC_SHA512_DIGEST_LENGTH
];
62 CC_SHA512_Final(digest_buffer
, &cc_context
);
63 set(kSecTransformOutputAttributeName
, CFDataCreate(NULL
, digest_buffer
, CC_SHA512_DIGEST_LENGTH
));
70 return (CFTypeRef
)CreateSecTransformErrorRef(kSecTransformErrorInvalidLength
, "Invalid length.");
72 return (CFTypeRef
)CreateSecTransformErrorRef(kSecTransformErrorInvalidAlgorithm
, "Invalid algorithm.");
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
);