2 * Copyright (c) 2008-2010,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 <Security/SecImportExport.h>
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>
34 #include <Security/SecCertificate.h>
36 #include <Security/SecInternal.h>
37 #include <CoreFoundation/CoreFoundation.h>
41 #include "shared_regressions.h"
42 #include "si-61-pkcs12.h"
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
);
52 CFDictionaryRemoveAllValues(query
);
53 CFDictionaryAddValue(query
, kSecClass
, kSecClassKey
);
54 CFDictionaryAddValue(query
, kSecValueRef
, pkey
);
61 static void tests(void)
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
;
69 #pragma clang diagnostic push
70 #pragma clang diagnostic ignored "-Wnonnull"
71 // Disable compile-time nullability checks, otherwise the code below won't compile.
73 is_status(SecPKCS12Import(message
, NULL
, NULL
), errSecAuthFailed
,
74 "try null password on a known good p12");
76 is_status(SecPKCS12Import(message
, NULL
, NULL
), errSecPassphraseRequired
,
77 "try null password on a known good p12");
79 #pragma clang diagnostic pop
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");
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");
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");
99 /* We need to delete the identity from the keychain because SecPKCS12Import imports to the
100 * keychain on macOS. */
101 delete_identity(cert
, pkey
);
104 CFReleaseNull(items
);
105 CFReleaseNull(message
);
106 CFReleaseNull(options
);
107 CFReleaseNull(password
);
111 message
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
,
112 _user_two_p12
, sizeof(_user_two_p12
), kCFAllocatorNull
);
114 password
= CFSTR("user-two");
115 options
= CFDictionaryCreate(NULL
,
116 (const void **)&kSecImportExportPassphrase
,
117 (const void **)&password
, 1,
118 &kCFTypeDictionaryKeyCallBacks
,
119 &kCFTypeDictionaryValueCallBacks
);
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");
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");
131 delete_identity(cert
, pkey
);
135 CFReleaseNull(items
);
136 CFReleaseNull(message
);
137 CFReleaseNull(options
);
138 CFReleaseNull(password
);
144 message
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
,
145 ECDSA_fails_import_p12
, ECDSA_fails_import_p12_len
, kCFAllocatorNull
);
147 password
= CFSTR("test");
148 options
= CFDictionaryCreate(NULL
,
149 (const void **)&kSecImportExportPassphrase
,
150 (const void **)&password
, 1,
151 &kCFTypeDictionaryKeyCallBacks
,
152 &kCFTypeDictionaryValueCallBacks
);
154 ok_status(SecPKCS12Import(message
, options
, &items
), "import ECDSA_fails_import_p12");
156 is(CFArrayGetCount(items
), 2, "two identities"); //macOS implementation doesn't dedup
158 is(CFArrayGetCount(items
), 1, "one identity");
160 item
= CFArrayGetValueAtIndex(items
, 0);
161 ok(identity
= (SecIdentityRef
)CFDictionaryGetValue(item
, kSecImportItemIdentity
), "pull identity from imported data");
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");
167 SecKeyRef pubkey
= NULL
;
169 ok(pubkey
= SecCertificateCopyKey(cert
), "get public key from cert");
171 ok(pubkey
= SecKeyCopyPublicKey(pkey
), "get public key from private key");
173 CFReleaseNull(message
);
175 /* Sign something. */
176 uint8_t something
[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
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");
184 delete_identity(cert
, pkey
);
187 CFReleaseNull(pubkey
);
190 CFDataRef pubdata
= NULL
;
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
),
198 ok(SecKeyVerifySignature(pubkey
, kSecKeyAlgorithmECDSASignatureMessageX962SHA256
, message
, signature
, &error
), "verify sig on something");
200 CFReleaseNull(pubdata
);
201 CFReleaseNull(pubkey
);
203 CFReleaseNull(signature
);
204 CFReleaseNull(items
);
205 CFReleaseNull(message
);
206 CFReleaseNull(options
);
207 CFReleaseNull(password
);
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");
221 item
= CFArrayGetValueAtIndex(items
, 0);
222 ok(identity
= (SecIdentityRef
)CFDictionaryGetValue(item
, kSecImportItemIdentity
), "pull identity from imported data");
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");
230 delete_identity(cert
, pkey
);
233 CFReleaseNull(items
);
234 CFReleaseNull(cert_p521_p12
);
235 CFReleaseNull(password_p521
);
236 CFReleaseNull(options_p521
);
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
);
252 is(SecPKCS12Import(message
, options
, &items
), errSecDecode
, "import cert decode failure p12");
254 is(SecPKCS12Import(message
, options
, &items
), errSecUnknownFormat
, "import cert decode failure p12");
256 CFReleaseNull(message
);
257 CFReleaseNull(items
);
258 CFReleaseNull(options
);
262 int si_61_pkcs12(int argc
, char *const *argv
)
267 test_cert_decode_error();