5 // Created by Mitch Adler on 7/18/12.
9 #include <SecureObjectSync/SOSInternal.h>
10 #include <SecureObjectSync/SOSCircle.h>
11 #include <SecureObjectSync/SOSCloudCircle.h>
12 #include <SecureObjectSync/SOSAccount.h>
14 #include "utilities/SecCFError.h"
15 #include "utilities/SecCFRelease.h"
16 #include "utilities/SecCFWrappers.h"
17 #include "utilities/iOSforOSX.h"
19 #include <CoreFoundation/CoreFoundation.h>
21 #include <Security/SecKey.h>
22 #include <Security/SecKeyPriv.h>
23 #include <Security/SecItem.h>
24 #include <securityd/SecDbItem.h> // For SecError
25 #include "utilities/iOSforOSX.h"
27 #include <Security/SecBase64.h>
29 #include <AssertMacros.h>
31 CFStringRef kSOSErrorDomain
= CFSTR("com.apple.security.sos.error");
33 bool SOSCreateError(CFIndex errorCode
, CFStringRef descriptionString
, CFErrorRef previousError
, CFErrorRef
*newError
) {
34 SOSCreateErrorWithFormat(errorCode
, previousError
, newError
, NULL
, CFSTR("%@"), descriptionString
);
38 bool SOSCreateErrorWithFormat(CFIndex errorCode
, CFErrorRef previousError
, CFErrorRef
*newError
,
39 CFDictionaryRef formatOptions
, CFStringRef format
, ...) {
42 bool res
= SOSCreateErrorWithFormatAndArguments(errorCode
, previousError
, newError
, formatOptions
, format
, va
);
47 bool SOSCreateErrorWithFormatAndArguments(CFIndex errorCode
, CFErrorRef previousError
, CFErrorRef
*newError
,
48 CFDictionaryRef formatOptions
, CFStringRef format
, va_list args
)
50 SecCFCreateErrorWithFormatAndArguments(errorCode
, kSOSErrorDomain
, previousError
, newError
, formatOptions
, format
, args
);
59 static OSStatus
GenerateECPairImp(int keySize
, CFBooleanRef permanent
, SecKeyRef
* public, SecKeyRef
*full
)
61 static const CFStringRef sTempNameToUse
= CFSTR("GenerateECPair Temporary Key - Shouldn't be live");
63 CFNumberRef signing_bitsize
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &keySize
);
65 CFDictionaryRef keygen_parameters
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
,
66 kSecAttrKeyType
, kSecAttrKeyTypeEC
,
67 kSecAttrKeySizeInBits
, signing_bitsize
,
68 kSecAttrIsPermanent
, permanent
,
69 kSecAttrLabel
, sTempNameToUse
,
71 CFReleaseNull(signing_bitsize
);
72 OSStatus result
= SecKeyGeneratePair(keygen_parameters
, public, full
);
73 CFReleaseNull(keygen_parameters
);
78 OSStatus
GenerateECPair(int keySize
, SecKeyRef
* public, SecKeyRef
*full
)
80 return GenerateECPairImp(keySize
, kCFBooleanFalse
, public, full
);
83 OSStatus
GeneratePermanentECPair(int keySize
, SecKeyRef
* public, SecKeyRef
*full
)
85 return GenerateECPairImp(keySize
, kCFBooleanTrue
, public, full
);
88 static CFStringRef
SOSCircleCopyDescriptionFromData(CFDataRef data
)
91 CFStringRef result
= NULL
;
93 SOSCircleRef circle
= SOSCircleCreateFromData(kCFAllocatorDefault
, data
, &error
);
96 result
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%@"), circle
);
98 CFReleaseSafe(circle
);
103 CFStringRef
SOSChangesCopyDescription(CFDictionaryRef changes
, bool is_sender
)
105 CFMutableStringRef string
= CFStringCreateMutableCopy(kCFAllocatorDefault
, 0, CFSTR("<Changes: {\n"));
107 CFDictionaryForEach(changes
, ^(const void *key
, const void *value
) {
108 CFStringRef value_description
= NULL
;
109 if (isString(key
) && isData(value
)) {
110 CFDataRef value_data
= (CFDataRef
) value
;
111 switch (SOSKVSKeyGetKeyType(key
)) {
113 value_description
= SOSCircleCopyDescriptionFromData(value_data
);
116 value_description
= SOSMessageCopyDescription(value_data
);
123 CFStringAppendFormat(string
, NULL
, CFSTR(" '%@' %s %@\n"),
125 is_sender
? "<=" : "=>",
126 value_description
? value_description
: value
);
128 CFReleaseNull(value_description
);
131 CFStringAppendFormat(string
, NULL
, CFSTR("}"));
136 CFStringRef
SOSCopyIDOfKey(SecKeyRef key
, CFErrorRef
*error
)
138 const struct ccdigest_info
* di
= ccsha1_di();
139 CFDataRef publicBytes
= NULL
;
140 CFStringRef result
= NULL
;
142 uint8_t digest
[di
->output_size
];
143 char encoded
[2 * di
->output_size
]; // Big enough for base64 encoding.
145 require_quiet(SecError(SecKeyCopyPublicBytes(key
, &publicBytes
), error
, CFSTR("Failed to export public bytes %@"), key
), fail
);
147 ccdigest(di
, CFDataGetLength(publicBytes
), CFDataGetBytePtr(publicBytes
), digest
);
149 size_t length
= SecBase64Encode(digest
, sizeof(digest
), encoded
, sizeof(encoded
));
150 assert(length
&& length
< sizeof(encoded
));
154 CFReleaseNull(publicBytes
);
155 return CFStringCreateWithCString(kCFAllocatorDefault
, encoded
, kCFStringEncodingASCII
);
158 CFReleaseNull(publicBytes
);