]> git.saurik.com Git - apple/security.git/blob - sec/SOSCircle/SecureObjectSync/SOSInternal.c
Security-55471.14.8.tar.gz
[apple/security.git] / sec / SOSCircle / SecureObjectSync / SOSInternal.c
1 //
2 // SOSInternal.c
3 // sec
4 //
5 // Created by Mitch Adler on 7/18/12.
6 //
7 //
8
9 #include <SecureObjectSync/SOSInternal.h>
10 #include <SecureObjectSync/SOSCircle.h>
11 #include <SecureObjectSync/SOSCloudCircle.h>
12 #include <SecureObjectSync/SOSAccount.h>
13
14 #include "utilities/SecCFError.h"
15 #include "utilities/SecCFRelease.h"
16 #include "utilities/SecCFWrappers.h"
17 #include "utilities/iOSforOSX.h"
18
19 #include <CoreFoundation/CoreFoundation.h>
20
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"
26
27 #include <Security/SecBase64.h>
28
29 #include <AssertMacros.h>
30
31 CFStringRef kSOSErrorDomain = CFSTR("com.apple.security.sos.error");
32
33 bool SOSCreateError(CFIndex errorCode, CFStringRef descriptionString, CFErrorRef previousError, CFErrorRef *newError) {
34 SOSCreateErrorWithFormat(errorCode, previousError, newError, NULL, CFSTR("%@"), descriptionString);
35 return true;
36 }
37
38 bool SOSCreateErrorWithFormat(CFIndex errorCode, CFErrorRef previousError, CFErrorRef *newError,
39 CFDictionaryRef formatOptions, CFStringRef format, ...) {
40 va_list va;
41 va_start(va, format);
42 bool res = SOSCreateErrorWithFormatAndArguments(errorCode, previousError, newError, formatOptions, format, va);
43 va_end(va);
44 return res;
45 }
46
47 bool SOSCreateErrorWithFormatAndArguments(CFIndex errorCode, CFErrorRef previousError, CFErrorRef *newError,
48 CFDictionaryRef formatOptions, CFStringRef format, va_list args)
49 {
50 SecCFCreateErrorWithFormatAndArguments(errorCode, kSOSErrorDomain, previousError, newError, formatOptions, format, args);
51 return true;
52 }
53
54
55 //
56 // Utility Functions
57 //
58
59 static OSStatus GenerateECPairImp(int keySize, CFBooleanRef permanent, SecKeyRef* public, SecKeyRef *full)
60 {
61 static const CFStringRef sTempNameToUse = CFSTR("GenerateECPair Temporary Key - Shouldn't be live");
62
63 CFNumberRef signing_bitsize = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &keySize);
64
65 CFDictionaryRef keygen_parameters = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
66 kSecAttrKeyType, kSecAttrKeyTypeEC,
67 kSecAttrKeySizeInBits, signing_bitsize,
68 kSecAttrIsPermanent, permanent,
69 kSecAttrLabel, sTempNameToUse,
70 NULL);
71 CFReleaseNull(signing_bitsize);
72 OSStatus result = SecKeyGeneratePair(keygen_parameters, public, full);
73 CFReleaseNull(keygen_parameters);
74
75 return result;
76 }
77
78 OSStatus GenerateECPair(int keySize, SecKeyRef* public, SecKeyRef *full)
79 {
80 return GenerateECPairImp(keySize, kCFBooleanFalse, public, full);
81 }
82
83 OSStatus GeneratePermanentECPair(int keySize, SecKeyRef* public, SecKeyRef *full)
84 {
85 return GenerateECPairImp(keySize, kCFBooleanTrue, public, full);
86 }
87
88 static CFStringRef SOSCircleCopyDescriptionFromData(CFDataRef data)
89 {
90 CFErrorRef error;
91 CFStringRef result = NULL;
92
93 SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, data, &error);
94
95 if (circle)
96 result = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@"), circle);
97
98 CFReleaseSafe(circle);
99
100 return result;
101 }
102
103 CFStringRef SOSChangesCopyDescription(CFDictionaryRef changes, bool is_sender)
104 {
105 CFMutableStringRef string = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFSTR("<Changes: {\n"));
106
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)) {
112 case kCircleKey:
113 value_description = SOSCircleCopyDescriptionFromData(value_data);
114 break;
115 case kMessageKey:
116 value_description = SOSMessageCopyDescription(value_data);
117 break;
118 default:
119 break;
120 }
121
122 }
123 CFStringAppendFormat(string, NULL, CFSTR(" '%@' %s %@\n"),
124 key,
125 is_sender ? "<=" : "=>",
126 value_description ? value_description : value);
127
128 CFReleaseNull(value_description);
129 });
130
131 CFStringAppendFormat(string, NULL, CFSTR("}"));
132
133 return string;
134 }
135
136 CFStringRef SOSCopyIDOfKey(SecKeyRef key, CFErrorRef *error)
137 {
138 const struct ccdigest_info * di = ccsha1_di();
139 CFDataRef publicBytes = NULL;
140 CFStringRef result = NULL;
141
142 uint8_t digest[di->output_size];
143 char encoded[2 * di->output_size]; // Big enough for base64 encoding.
144
145 require_quiet(SecError(SecKeyCopyPublicBytes(key, &publicBytes), error, CFSTR("Failed to export public bytes %@"), key), fail);
146
147 ccdigest(di, CFDataGetLength(publicBytes), CFDataGetBytePtr(publicBytes), digest);
148
149 size_t length = SecBase64Encode(digest, sizeof(digest), encoded, sizeof(encoded));
150 assert(length && length < sizeof(encoded));
151 if (length > 26)
152 length = 26;
153 encoded[length] = 0;
154 CFReleaseNull(publicBytes);
155 return CFStringCreateWithCString(kCFAllocatorDefault, encoded, kCFStringEncodingASCII);
156
157 fail:
158 CFReleaseNull(publicBytes);
159 return result;
160 }