2 * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
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"
34 #include <CoreFoundation/CoreFoundation.h>
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"
42 #include <Security/SecBase64.h>
44 #include <AssertMacros.h>
46 CFStringRef kSOSErrorDomain
= CFSTR("com.apple.security.sos.error");
48 bool SOSErrorCreate(CFIndex errorCode
, CFErrorRef
*error
, CFDictionaryRef formatOptions
, CFStringRef format
, ...) {
49 if (!errorCode
) return true;
50 if (error
&& !*error
) {
53 SecCFCreateErrorWithFormatAndArguments(errorCode
, kSOSErrorDomain
, NULL
, error
, formatOptions
, format
, va
);
59 bool SOSCreateError(CFIndex errorCode
, CFStringRef descriptionString
, CFErrorRef previousError
, CFErrorRef
*newError
) {
60 SOSCreateErrorWithFormat(errorCode
, previousError
, newError
, NULL
, CFSTR("%@"), descriptionString
);
64 bool SOSCreateErrorWithFormat(CFIndex errorCode
, CFErrorRef previousError
, CFErrorRef
*newError
,
65 CFDictionaryRef formatOptions
, CFStringRef format
, ...) {
68 bool res
= SOSCreateErrorWithFormatAndArguments(errorCode
, previousError
, newError
, formatOptions
, format
, va
);
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
);
84 static OSStatus
GenerateECPairImp(int keySize
, CFBooleanRef permanent
, SecKeyRef
* public, SecKeyRef
*full
)
86 static const CFStringRef sTempNameToUse
= CFSTR("GenerateECPair Temporary Key - Shouldn't be live");
88 CFNumberRef signing_bitsize
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &keySize
);
90 CFDictionaryRef keygen_parameters
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
,
91 kSecAttrKeyType
, kSecAttrKeyTypeEC
,
92 kSecAttrKeySizeInBits
, signing_bitsize
,
93 kSecAttrIsPermanent
, permanent
,
94 kSecAttrLabel
, sTempNameToUse
,
96 CFReleaseNull(signing_bitsize
);
97 OSStatus result
= SecKeyGeneratePair(keygen_parameters
, public, full
);
98 CFReleaseNull(keygen_parameters
);
103 OSStatus
GenerateECPair(int keySize
, SecKeyRef
* public, SecKeyRef
*full
)
105 return GenerateECPairImp(keySize
, kCFBooleanFalse
, public, full
);
108 OSStatus
GeneratePermanentECPair(int keySize
, SecKeyRef
* public, SecKeyRef
*full
)
110 return GenerateECPairImp(keySize
, kCFBooleanTrue
, public, full
);
113 static CFStringRef
SOSCircleCopyDescriptionFromData(CFDataRef data
)
115 CFErrorRef error
= NULL
;
116 CFStringRef result
= NULL
;
118 SOSCircleRef circle
= SOSCircleCreateFromData(kCFAllocatorDefault
, data
, &error
);
121 result
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%@"), circle
);
123 CFReleaseSafe(circle
);
128 CFStringRef
SOSChangesCopyDescription(CFDictionaryRef changes
, bool is_sender
)
130 CFMutableStringRef string
= CFStringCreateMutableCopy(kCFAllocatorDefault
, 0, CFSTR("<Changes: {\n"));
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
)) {
138 value_description
= SOSCircleCopyDescriptionFromData(value_data
);
141 value_description
= CFCopyDescription(value_data
);
148 CFStringAppendFormat(string
, NULL
, CFSTR(" '%@' %s %@\n"),
150 is_sender
? "<=" : "=>",
151 value_description
? value_description
: value
);
153 CFReleaseNull(value_description
);
156 CFStringAppendFormat(string
, NULL
, CFSTR("}"));
161 CFStringRef
SOSCopyIDOfKey(SecKeyRef key
, CFErrorRef
*error
)
163 const struct ccdigest_info
* di
= ccsha1_di();
164 CFDataRef publicBytes
= NULL
;
165 CFStringRef result
= NULL
;
167 uint8_t digest
[di
->output_size
];
168 char encoded
[2 * di
->output_size
]; // Big enough for base64 encoding.
170 require_quiet(SecError(SecKeyCopyPublicBytes(key
, &publicBytes
), error
, CFSTR("Failed to export public bytes %@"), key
), fail
);
172 ccdigest(di
, CFDataGetLength(publicBytes
), CFDataGetBytePtr(publicBytes
), digest
);
174 size_t length
= SecBase64Encode(digest
, sizeof(digest
), encoded
, sizeof(encoded
));
175 assert(length
&& length
< sizeof(encoded
));
179 CFReleaseNull(publicBytes
);
180 return CFStringCreateWithCString(kCFAllocatorDefault
, encoded
, kCFStringEncodingASCII
);
183 CFReleaseNull(publicBytes
);