]>
Commit | Line | Data |
---|---|---|
427c49bc | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2008-2010,2012-2014 Apple Inc. All Rights Reserved. |
427c49bc | 3 | * |
d8f41ccd A |
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@ | |
427c49bc A |
22 | */ |
23 | ||
d8f41ccd | 24 | |
427c49bc A |
25 | #include <Security/SecImportExport.h> |
26 | ||
27 | #include <CommonCrypto/CommonCryptor.h> | |
28 | #include <Security/SecIdentity.h> | |
29 | #include <Security/SecItem.h> | |
30 | #include <Security/SecItemPriv.h> | |
31 | #include <Security/SecBasePriv.h> | |
32 | #include <Security/SecKey.h> | |
33 | #include <Security/SecECKey.h> | |
866f8763 | 34 | #include <Security/SecCertificate.h> |
427c49bc A |
35 | |
36 | #include <Security/SecInternal.h> | |
37 | #include <CoreFoundation/CoreFoundation.h> | |
38 | #include <stdlib.h> | |
39 | #include <unistd.h> | |
40 | ||
866f8763 A |
41 | #include "shared_regressions.h" |
42 | #include "si-61-pkcs12.h" | |
43 | ||
44 | #if TARGET_OS_OSX | |
45 | static void delete_identity(SecCertificateRef cert, SecKeyRef pkey) { | |
46 | CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 2, &kCFTypeDictionaryKeyCallBacks, | |
47 | &kCFTypeDictionaryValueCallBacks); | |
48 | CFDictionaryAddValue(query, kSecClass, kSecClassCertificate); | |
49 | CFDictionaryAddValue(query, kSecValueRef, cert); | |
50 | SecItemDelete(query); | |
51 | ||
52 | CFDictionaryRemoveAllValues(query); | |
53 | CFDictionaryAddValue(query, kSecClass, kSecClassKey); | |
54 | CFDictionaryAddValue(query, kSecValueRef, pkey); | |
55 | SecItemDelete(query); | |
56 | CFReleaseNull(query); | |
57 | } | |
58 | #endif | |
5c19dc3a A |
59 | |
60 | ||
427c49bc A |
61 | static void tests(void) |
62 | { | |
63 | CFDataRef message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, | |
64 | _user_one_p12, sizeof(_user_one_p12), kCFAllocatorNull); | |
65 | CFArrayRef items = NULL; | |
66 | SecCertificateRef cert = NULL; | |
67 | SecKeyRef pkey = NULL; | |
68 | ||
5c19dc3a A |
69 | #pragma clang diagnostic push |
70 | #pragma clang diagnostic ignored "-Wnonnull" | |
71 | // Disable compile-time nullability checks, otherwise the code below won't compile. | |
866f8763 | 72 | #if TARGET_OS_IPHONE |
427c49bc A |
73 | is_status(SecPKCS12Import(message, NULL, NULL), errSecAuthFailed, |
74 | "try null password on a known good p12"); | |
866f8763 A |
75 | #else |
76 | is_status(SecPKCS12Import(message, NULL, NULL), errSecPassphraseRequired, | |
77 | "try null password on a known good p12"); | |
78 | #endif | |
5c19dc3a | 79 | #pragma clang diagnostic pop |
427c49bc A |
80 | |
81 | CFStringRef password = CFSTR("user-one"); | |
82 | CFDictionaryRef options = CFDictionaryCreate(NULL, | |
83 | (const void **)&kSecImportExportPassphrase, | |
84 | (const void **)&password, 1, | |
85 | &kCFTypeDictionaryKeyCallBacks, | |
86 | &kCFTypeDictionaryValueCallBacks); | |
87 | ok_status(SecPKCS12Import(message, options, &items), "import user one"); | |
88 | ||
89 | is(CFArrayGetCount(items), 1, "one identity"); | |
90 | CFDictionaryRef item = CFArrayGetValueAtIndex(items, 0); | |
91 | SecIdentityRef identity = NULL; | |
92 | ok(identity = (SecIdentityRef)CFDictionaryGetValue(item, kSecImportItemIdentity), "pull identity from imported data"); | |
93 | ||
94 | ok(CFGetTypeID(identity)==SecIdentityGetTypeID(),"this is a SecIdentityRef"); | |
95 | ok_status(SecIdentityCopyPrivateKey(identity, &pkey),"get private key"); | |
96 | ok_status(SecIdentityCopyCertificate(identity, &cert), "get certificate"); | |
97 | ||
866f8763 A |
98 | #if TARGET_OS_OSX |
99 | /* We need to delete the identity from the keychain because SecPKCS12Import imports to the | |
100 | * keychain on macOS. */ | |
101 | delete_identity(cert, pkey); | |
102 | #endif | |
103 | ||
427c49bc A |
104 | CFReleaseNull(items); |
105 | CFReleaseNull(message); | |
106 | CFReleaseNull(options); | |
107 | CFReleaseNull(password); | |
108 | CFReleaseNull(cert); | |
109 | CFReleaseNull(pkey); | |
110 | ||
111 | message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, | |
112 | _user_two_p12, sizeof(_user_two_p12), kCFAllocatorNull); | |
113 | items = NULL; | |
114 | password = CFSTR("user-two"); | |
115 | options = CFDictionaryCreate(NULL, | |
116 | (const void **)&kSecImportExportPassphrase, | |
117 | (const void **)&password, 1, | |
118 | &kCFTypeDictionaryKeyCallBacks, | |
119 | &kCFTypeDictionaryValueCallBacks); | |
120 | ||
121 | ok_status(SecPKCS12Import(message, options, &items), "import user two"); | |
122 | is(CFArrayGetCount(items), 1, "one identity"); | |
123 | item = CFArrayGetValueAtIndex(items, 0); | |
124 | ok(identity = (SecIdentityRef)CFDictionaryGetValue(item, kSecImportItemIdentity), "pull identity from imported data"); | |
125 | ||
126 | ok(CFGetTypeID(identity)==SecIdentityGetTypeID(),"this is a SecIdentityRef"); | |
127 | ok_status(SecIdentityCopyPrivateKey(identity, &pkey),"get private key"); | |
128 | ok_status(SecIdentityCopyCertificate(identity, &cert), "get certificate"); | |
129 | ||
866f8763 A |
130 | #if TARGET_OS_OSX |
131 | delete_identity(cert, pkey); | |
132 | #endif | |
133 | ||
134 | ||
427c49bc A |
135 | CFReleaseNull(items); |
136 | CFReleaseNull(message); | |
137 | CFReleaseNull(options); | |
138 | CFReleaseNull(password); | |
139 | CFReleaseNull(cert); | |
140 | CFReleaseNull(pkey); | |
141 | ||
142 | ||
143 | ||
144 | message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, | |
145 | ECDSA_fails_import_p12, ECDSA_fails_import_p12_len, kCFAllocatorNull); | |
146 | items = NULL; | |
147 | password = CFSTR("test"); | |
148 | options = CFDictionaryCreate(NULL, | |
149 | (const void **)&kSecImportExportPassphrase, | |
150 | (const void **)&password, 1, | |
151 | &kCFTypeDictionaryKeyCallBacks, | |
152 | &kCFTypeDictionaryValueCallBacks); | |
153 | ||
154 | ok_status(SecPKCS12Import(message, options, &items), "import ECDSA_fails_import_p12"); | |
866f8763 A |
155 | #if TARGET_OS_OSX |
156 | is(CFArrayGetCount(items), 2, "two identities"); //macOS implementation doesn't dedup | |
157 | #else | |
427c49bc | 158 | is(CFArrayGetCount(items), 1, "one identity"); |
866f8763 | 159 | #endif |
427c49bc A |
160 | item = CFArrayGetValueAtIndex(items, 0); |
161 | ok(identity = (SecIdentityRef)CFDictionaryGetValue(item, kSecImportItemIdentity), "pull identity from imported data"); | |
162 | ||
163 | ok(CFGetTypeID(identity)==SecIdentityGetTypeID(),"this is a SecIdentityRef"); | |
164 | ok_status(SecIdentityCopyPrivateKey(identity, &pkey),"get private key"); | |
165 | ok_status(SecIdentityCopyCertificate(identity, &cert), "get certificate"); | |
166 | ||
427c49bc | 167 | SecKeyRef pubkey = NULL; |
866f8763 | 168 | #if TARGET_OS_OSX |
79b9da22 | 169 | ok(pubkey = SecCertificateCopyKey(cert), "get public key from cert"); |
866f8763 A |
170 | #else |
171 | ok(pubkey = SecKeyCopyPublicKey(pkey), "get public key from private key"); | |
172 | #endif | |
173 | CFReleaseNull(message); | |
427c49bc A |
174 | |
175 | /* Sign something. */ | |
176 | uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; | |
866f8763 A |
177 | message = CFDataCreateWithBytesNoCopy(NULL, something, sizeof(something), kCFAllocatorNull); |
178 | CFDataRef signature = NULL; | |
179 | CFErrorRef error = NULL; | |
180 | ok(signature = SecKeyCreateSignature(pkey, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, message, NULL), "sign something"); | |
181 | ok(SecKeyVerifySignature(pubkey, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, message, signature, NULL), "verify sig on something"); | |
427c49bc | 182 | |
866f8763 A |
183 | #if TARGET_OS_OSX |
184 | delete_identity(cert, pkey); | |
185 | #endif | |
427c49bc | 186 | |
427c49bc A |
187 | CFReleaseNull(pubkey); |
188 | CFReleaseNull(pkey); | |
189 | ||
866f8763 | 190 | CFDataRef pubdata = NULL; |
427c49bc A |
191 | ok(pkey = SecKeyCreateECPrivateKey(kCFAllocatorDefault, |
192 | ECDSA_fails_import_priv_only, ECDSA_fails_import_priv_only_len, | |
193 | kSecKeyEncodingPkcs1), "import privkey without pub"); | |
194 | ok_status(SecKeyCopyPublicBytes(pkey, &pubdata), "pub key from priv key"); | |
195 | ok(pubkey = SecKeyCreateECPublicKey(kCFAllocatorDefault, | |
196 | CFDataGetBytePtr(pubdata), CFDataGetLength(pubdata), kSecKeyEncodingBytes), | |
197 | "recreate seckey"); | |
866f8763 | 198 | ok(SecKeyVerifySignature(pubkey, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, message, signature, &error), "verify sig on something"); |
427c49bc A |
199 | |
200 | CFReleaseNull(pubdata); | |
201 | CFReleaseNull(pubkey); | |
202 | CFReleaseNull(pkey); | |
866f8763 | 203 | CFReleaseNull(signature); |
427c49bc A |
204 | CFReleaseNull(items); |
205 | CFReleaseNull(message); | |
206 | CFReleaseNull(options); | |
207 | CFReleaseNull(password); | |
208 | CFReleaseNull(cert); | |
209 | ||
5c19dc3a A |
210 | /* P521 test */ |
211 | CFDataRef cert_p521_p12 = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, | |
212 | ec521_host_pfx, sizeof(ec521_host_pfx), kCFAllocatorNull); | |
213 | CFStringRef password_p521 = CFSTR("test!123"); | |
214 | CFDictionaryRef options_p521 = CFDictionaryCreate(NULL, | |
215 | (const void **)&kSecImportExportPassphrase, | |
216 | (const void **)&password_p521, 1, | |
217 | &kCFTypeDictionaryKeyCallBacks, | |
218 | &kCFTypeDictionaryValueCallBacks); | |
219 | ok_status(SecPKCS12Import(cert_p521_p12, options_p521, &items), "Import p512 PKCS12 cert"); | |
220 | is(CFArrayGetCount(items), 1, "one identity"); | |
866f8763 A |
221 | item = CFArrayGetValueAtIndex(items, 0); |
222 | ok(identity = (SecIdentityRef)CFDictionaryGetValue(item, kSecImportItemIdentity), "pull identity from imported data"); | |
223 | ||
224 | ok(CFGetTypeID(identity)==SecIdentityGetTypeID(),"this is a SecIdentityRef"); | |
225 | ok_status(SecIdentityCopyPrivateKey(identity, &pkey),"get private key"); | |
226 | ok_status(SecIdentityCopyCertificate(identity, &cert), "get certificate"); | |
227 | ||
228 | ||
229 | #if TARGET_OS_OSX | |
230 | delete_identity(cert, pkey); | |
231 | #endif | |
232 | ||
5c19dc3a A |
233 | CFReleaseNull(items); |
234 | CFReleaseNull(cert_p521_p12); | |
235 | CFReleaseNull(password_p521); | |
236 | CFReleaseNull(options_p521); | |
866f8763 A |
237 | CFReleaseNull(pkey); |
238 | CFReleaseNull(cert); | |
239 | } | |
240 | ||
241 | static void test_cert_decode_error() { | |
242 | CFDataRef message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, _cert_decode_error_p12, | |
243 | sizeof(_cert_decode_error_p12), kCFAllocatorNull); | |
244 | CFArrayRef items = NULL; | |
245 | CFStringRef password = CFSTR("1234"); | |
246 | CFDictionaryRef options = CFDictionaryCreate(NULL, | |
247 | (const void **)&kSecImportExportPassphrase, | |
248 | (const void **)&password, 1, | |
249 | &kCFTypeDictionaryKeyCallBacks, | |
250 | &kCFTypeDictionaryValueCallBacks); | |
251 | #if TARGET_OS_IPHONE | |
252 | is(SecPKCS12Import(message, options, &items), errSecDecode, "import cert decode failure p12"); | |
253 | #else | |
254 | is(SecPKCS12Import(message, options, &items), errSecUnknownFormat, "import cert decode failure p12"); | |
255 | #endif | |
256 | CFReleaseNull(message); | |
257 | CFReleaseNull(items); | |
258 | CFReleaseNull(options); | |
259 | ||
427c49bc A |
260 | } |
261 | ||
262 | int si_61_pkcs12(int argc, char *const *argv) | |
263 | { | |
866f8763 | 264 | plan_tests(33); |
427c49bc A |
265 | |
266 | tests(); | |
866f8763 | 267 | test_cert_decode_error(); |
427c49bc A |
268 | |
269 | return 0; | |
270 | } |