2 * Copyright (c) 2011-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@
27 #include "Security_regressions.h"
29 #include <CoreFoundation/CFData.h>
30 #include <Security/SecOTRSession.h>
31 #include <Security/SecInternal.h>
32 #include <Security/SecBasePriv.h>
33 #include <Security/SecKey.h>
34 #include <Security/SecItem.h>
35 #include <utilities/SecCFWrappers.h>
36 #include <Security/SecOTRIdentityPriv.h>
38 static void RegressionsLogError(CFErrorRef error
) {
42 CFDictionaryRef tempDictionary
= CFErrorCopyUserInfo(error
);
43 CFIndex errorCode
= CFErrorGetCode(error
);
44 CFStringRef errorDomain
= CFErrorGetDomain(error
);
45 CFStringRef errorString
= CFDictionaryGetValue(tempDictionary
, kCFErrorDescriptionKey
);
46 CFErrorRef previousError
= (CFErrorRef
)CFDictionaryGetValue(tempDictionary
, kCFErrorUnderlyingErrorKey
);
47 if (previousError
!= NULL
) {
48 RegressionsLogError(previousError
);
50 char errorDomainStr
[1024];
51 char errorStringStr
[1024];
53 CFStringGetCString(errorDomain
, errorDomainStr
, 1024, kCFStringEncodingUTF8
);
54 CFStringGetCString(errorString
, errorStringStr
, 1024, kCFStringEncodingUTF8
);
55 printf("OTR: %s (%ld) -- %s\n", errorDomainStr
, errorCode
, errorStringStr
);
56 CFReleaseSafe(tempDictionary
);
59 static int kTestTestCount
= 27;
61 static void otr_00_identity_MessageProtectionKeys()
63 // We create a MessageProtection-style key.
64 int32_t keysz32
= 256;
65 CFNumberRef ksizeNumber
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &keysz32
);
66 CFDictionaryRef dict
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
,
67 kSecAttrKeyType
, kSecAttrKeyTypeECSECPrimeRandom
,
68 kSecAttrKeyClass
, kSecAttrKeyClassPrivate
,
69 kSecAttrKeySizeInBits
, ksizeNumber
,
70 kSecAttrIsPermanent
, kCFBooleanFalse
, NULL
);
72 CFErrorRef error
= NULL
;
73 SecKeyRef testIdentityKey
= SecKeyCreateRandomKey(dict
, &error
);
74 ok(testIdentityKey
!= NULL
, "Failed to create test key.");
76 CFReleaseSafe(ksizeNumber
);
79 SecOTRFullIdentityRef identity1
= SecOTRFullIdentityCreateFromSecKeyRef(kCFAllocatorDefault
, testIdentityKey
, &error
);
80 ok(identity1
->isMessageProtectionKey
, "Should be MessageProtection Key");
81 ok(identity1
->privateKeyPersistentRef
== NULL
, "MessageProtection key shouldn't have a peristent ref.");
83 CFMutableDataRef serializeInto
= CFDataCreateMutable(kCFAllocatorDefault
, 100);
84 SecOTRFIAppendSerialization(identity1
, serializeInto
, &error
);
86 SecOTRFullIdentityRef identity2
= SecOTRFullIdentityCreateFromData(kCFAllocatorDefault
, serializeInto
, &error
);
87 ok(identity2
->isMessageProtectionKey
, "Should still be a MessageProtection Key");
88 ok(identity2
->privateKeyPersistentRef
== NULL
, "MessageProtection key shouldn't have a peristent ref.");
90 CFDataRef serializedKey1
= SecKeyCopyExternalRepresentation(identity1
->privateSigningKey
, &error
);
91 CFDataRef serializedKey2
= SecKeyCopyExternalRepresentation(identity2
->privateSigningKey
, &error
);
93 ok(CFEqual(serializedKey1
, serializedKey2
));
94 ok(error
== NULL
, "Testing shouldn't cause any errors");
97 CFReleaseSafe(serializedKey1
);
98 CFReleaseSafe(serializedKey2
);
99 CFReleaseSafe(identity1
);
100 CFReleaseSafe(identity2
);
101 CFReleaseSafe(testIdentityKey
);
102 CFReleaseNull(serializeInto
);
105 static void tests(void)
107 CFErrorRef testError
= NULL
;
109 SecOTRFullIdentityRef idToPurge
= SecOTRFullIdentityCreate(kCFAllocatorDefault
, &testError
);
110 ok(idToPurge
!= NULL
, "Make Identity: %@", testError
);
111 ok(idToPurge
->isMessageProtectionKey
== false, "Keys shouldn't be defaulting to MessageProtection type");
112 RegressionsLogError(testError
);
113 CFReleaseNull(testError
);
115 CFMutableDataRef purgeExport
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
117 ok(SecOTRFIAppendSerialization(idToPurge
, purgeExport
, &testError
), "First export: %@", testError
);
118 RegressionsLogError(testError
);
119 CFReleaseNull(testError
);
121 SecOTRFullIdentityRef purgeIdInflate
= SecOTRFullIdentityCreateFromData(kCFAllocatorDefault
, purgeExport
, &testError
);
122 ok(purgeIdInflate
!= NULL
, "Inflate Identity: %@", testError
);
123 ok(idToPurge
->isMessageProtectionKey
== false, "Keys shouldn't be re-imported as MessageProtection types");
124 RegressionsLogError(testError
);
125 CFReleaseNull(testError
);
127 SecOTRFIPurgeFromKeychain(idToPurge
, &testError
);
128 RegressionsLogError(testError
);
129 CFReleaseNull(testError
);
131 SecOTRFullIdentityRef failIDInflate
= SecOTRFullIdentityCreateFromData(kCFAllocatorDefault
, purgeExport
, &testError
);
132 ok(failIDInflate
== NULL
, "Should fail: %@", testError
);
133 RegressionsLogError(testError
);
134 CFReleaseNull(testError
);
137 CFReleaseSafe(idToPurge
);
140 idToPurge
= SecOTRFullIdentityCreate(kCFAllocatorDefault
, &testError
);
141 ok(idToPurge
!= NULL
, "Make Identity again: %@", testError
);
142 RegressionsLogError(testError
);
143 CFReleaseNull(testError
);
145 SecOTRFIPurgeAllFromKeychain(&testError
);
146 RegressionsLogError(testError
);
147 CFReleaseNull(testError
);
149 SecOTRFullIdentityRef failIDInflate2
= SecOTRFullIdentityCreateFromData(kCFAllocatorDefault
, purgeExport
, &testError
);
150 ok(failIDInflate2
== NULL
, "Should fail 2: %@", testError
);
151 RegressionsLogError(testError
);
152 CFReleaseNull(testError
);
154 SecOTRFullIdentityRef id
= SecOTRFullIdentityCreate(kCFAllocatorDefault
, &testError
);
155 ok(id
!= NULL
, "Make Identity: %@", testError
);
156 RegressionsLogError(testError
);
157 CFReleaseNull(testError
);
159 CFMutableDataRef firstExport
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
161 ok(SecOTRFIAppendSerialization(id
, firstExport
, &testError
), "First export: %@", testError
);
162 RegressionsLogError(testError
);
163 CFReleaseNull(testError
);
165 SecOTRFullIdentityRef idInflate
= SecOTRFullIdentityCreateFromData(kCFAllocatorDefault
, firstExport
, &testError
);
166 ok(idInflate
!= NULL
, "Inflate Identity: %@", testError
);
167 RegressionsLogError(testError
);
168 CFReleaseNull(testError
);
170 CFMutableDataRef secondExport
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
172 ok(SecOTRFIAppendSerialization(idInflate
, secondExport
, &testError
), "second export: %@", testError
);
173 RegressionsLogError(testError
);
174 CFReleaseNull(testError
);
176 ok(CFDataGetLength(firstExport
) == CFDataGetLength(secondExport
)
177 && 0 == memcmp(CFDataGetBytePtr(firstExport
), CFDataGetBytePtr(secondExport
), (size_t)CFDataGetLength(firstExport
)), "Different exports");
179 SecOTRPublicIdentityRef pubID
= SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault
, id
, &testError
);
180 ok(id
!= NULL
, "Failed to copy public identity: %@", testError
);
181 RegressionsLogError(testError
);
182 CFReleaseNull(testError
);
184 CFMutableDataRef firstPublicExport
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
186 ok(SecOTRPIAppendSerialization(pubID
, firstPublicExport
, &testError
), "failed first public export: %@", testError
);
187 RegressionsLogError(testError
);
188 CFReleaseNull(testError
);
190 SecOTRPublicIdentityRef pubIDInflate
= SecOTRPublicIdentityCreateFromData(kCFAllocatorDefault
, firstPublicExport
, &testError
);
191 ok(pubIDInflate
!= NULL
, "Pub inflate failed: %@", testError
);
192 RegressionsLogError(testError
);
193 CFReleaseNull(testError
);
195 CFMutableDataRef secondPublicExport
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
197 ok(SecOTRPIAppendSerialization(pubID
, secondPublicExport
, &testError
), "failed second public export: %@", testError
);
198 RegressionsLogError(testError
);
199 CFReleaseNull(testError
);
201 ok(CFDataGetLength(firstPublicExport
) == CFDataGetLength(secondPublicExport
)
202 && 0 == memcmp(CFDataGetBytePtr(firstPublicExport
), CFDataGetBytePtr(secondPublicExport
), (size_t)CFDataGetLength(firstPublicExport
)), "Different public exports");
204 uint8_t sampleByteString
[] = {
205 0x30, 0x81, 0xf6, 0x81, 0x43, 0x00, 0x41, 0x04, 0xc6, 0x8a, 0x2a, 0x5c, 0x29, 0xa4, 0xb7, 0x58,
206 0xe1, 0x3c, 0x07, 0x19, 0x20, 0xf3, 0x0b, 0xb8, 0xb3, 0x40, 0x41, 0x29, 0x4a, 0xa6, 0x7a, 0x56,
207 0x28, 0x6d, 0x10, 0x85, 0x2b, 0x14, 0x83, 0xaa, 0x1f, 0x6a, 0x47, 0xbc, 0x19, 0x26, 0x39, 0x1c,
208 0xd4, 0xbb, 0x8c, 0xd6, 0x94, 0x24, 0x79, 0x60, 0xfb, 0x8e, 0x4b, 0xf4, 0x0f, 0xbf, 0x38, 0x81,
209 0x78, 0xce, 0x1d, 0xd9, 0x03, 0xec, 0x65, 0xcd, 0x82, 0x81, 0xae, 0x00, 0xac, 0x30, 0x81, 0xa9,
210 0x02, 0x81, 0xa1, 0x00, 0xd2, 0xf4, 0x40, 0x8b, 0x2f, 0x09, 0x75, 0x2c, 0x68, 0x12, 0x76, 0xb9,
211 0xfb, 0x1b, 0x02, 0x91, 0x6d, 0xd7, 0x86, 0x49, 0xdc, 0xef, 0x38, 0xf3, 0x50, 0x58, 0xb5, 0xff,
212 0x5c, 0x02, 0x8a, 0xb0, 0xcd, 0xb3, 0x3d, 0x94, 0x71, 0x7d, 0x32, 0x53, 0xed, 0x43, 0xfb, 0xde,
213 0xbc, 0x20, 0x21, 0x33, 0xe3, 0xeb, 0x93, 0x48, 0xe8, 0xd1, 0x32, 0x2f, 0x40, 0x40, 0x47, 0x1f,
214 0xeb, 0x7e, 0xf6, 0x43, 0x81, 0x51, 0xd6, 0x4f, 0xe0, 0x57, 0xbf, 0x12, 0xeb, 0x18, 0x2e, 0x81,
215 0x0b, 0x3a, 0x04, 0xf1, 0xeb, 0x3c, 0xe1, 0xb9, 0xf4, 0x87, 0x37, 0x83, 0x5a, 0x2e, 0x09, 0xf8,
216 0xd5, 0xa0, 0x12, 0xfb, 0x35, 0xe4, 0xd4, 0x3f, 0xef, 0x24, 0x3e, 0x6c, 0xff, 0xb1, 0x35, 0x7e,
217 0x9f, 0xe7, 0x6d, 0x2f, 0xf8, 0x0d, 0xc6, 0xbc, 0x19, 0xe2, 0x78, 0xb3, 0x71, 0xe1, 0x35, 0xe7,
218 0xc7, 0x22, 0x6b, 0x4d, 0x92, 0xc4, 0x10, 0x75, 0x1a, 0x9b, 0x9f, 0x7f, 0xac, 0x2d, 0xfb, 0xc9,
219 0x64, 0x1e, 0x80, 0x11, 0x7f, 0x75, 0x8a, 0x86, 0x7e, 0x09, 0x44, 0xc4, 0x71, 0xbf, 0xd4, 0xfa,
220 0x8b, 0x6a, 0xb8, 0x9f, 0x02, 0x03, 0x01, 0x00,
223 CFDataRef testInteropImport
= CFDataCreate(kCFAllocatorDefault
, sampleByteString
, sizeof(sampleByteString
));
224 SecOTRPublicIdentityRef interopIDInflate
= SecOTRPublicIdentityCreateFromData(kCFAllocatorDefault
, testInteropImport
, &testError
);
225 RegressionsLogError(testError
);
226 CFReleaseNull(testError
);
227 ok(interopIDInflate
!= NULL
, "Interop inflate failed");
229 /* cleanup keychain */
230 ok(SecOTRFIPurgeAllFromKeychain(&testError
),"cleanup keychain");
231 RegressionsLogError(testError
);
232 CFReleaseNull(testError
);
234 CFReleaseSafe(pubID
);
235 CFReleaseSafe(pubIDInflate
);
236 CFReleaseSafe(firstPublicExport
);
237 CFReleaseSafe(secondPublicExport
);
239 CFReleaseSafe(idToPurge
);
240 CFReleaseSafe(idInflate
);
241 CFReleaseSafe(firstExport
);
242 CFReleaseSafe(secondExport
);
243 CFReleaseSafe(purgeExport
);
244 CFReleaseSafe(purgeIdInflate
);
245 CFReleaseSafe(failIDInflate
);
246 CFReleaseSafe(failIDInflate2
);
247 CFReleaseSafe(testInteropImport
);
248 CFReleaseSafe(interopIDInflate
);
250 otr_00_identity_MessageProtectionKeys();
255 int otr_00_identity(int argc
, char *const *argv
)
257 plan_tests(kTestTestCount
);