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