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/SecKey.h>
26 #include <Security/SecItem.h>
27 #include <Security/SecItemPriv.h>
28 #include <Security/SecCMS.h>
29 #include <Security/SecCertificateRequest.h>
30 #include <Security/SecSCEP.h>
31 #include <Security/SecCertificatePriv.h>
32 #include <Security/SecIdentityPriv.h>
33 #include <utilities/array_size.h>
35 #include <Security/SecInternal.h>
36 #include <CoreFoundation/CoreFoundation.h>
40 #include "shared_regressions.h"
43 __unused
static inline void write_data(const char * path
, CFDataRef data
)
45 int data_file
= open(path
, O_CREAT
|O_WRONLY
|O_TRUNC
, 0644);
46 write(data_file
, CFDataGetBytePtr(data
), CFDataGetLength(data
));
51 static void tests(void)
53 SecKeyRef phone_publicKey
= NULL
, phone_privateKey
= NULL
;
54 SecKeyRef ca_publicKey
= NULL
, ca_privateKey
= NULL
;
57 CFNumberRef key_size_num
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &keysize
);
58 const void *keygen_keys
[] = { kSecAttrKeyType
, kSecAttrKeySizeInBits
};
59 const void *keygen_vals
[] = { kSecAttrKeyTypeRSA
, key_size_num
};
60 CFDictionaryRef parameters
= CFDictionaryCreate(kCFAllocatorDefault
,
61 keygen_keys
, keygen_vals
, array_size(keygen_vals
),
62 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
63 CFReleaseNull(key_size_num
);
65 CFMutableDictionaryRef subject_alt_names
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
66 CFDictionarySetValue(subject_alt_names
, CFSTR("dnsname"), CFSTR("xey.nl"));
68 int key_usage
= kSecKeyUsageDigitalSignature
| kSecKeyUsageKeyEncipherment
;
69 CFNumberRef key_usage_num
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &key_usage
);
71 CFMutableDictionaryRef random_extensions
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
73 const void *key
[] = { kSecCSRChallengePassword
, kSecSubjectAltName
, kSecCertificateKeyUsage
, kSecCertificateExtensions
};
74 const void *val
[] = { CFSTR("magic"), subject_alt_names
, key_usage_num
, random_extensions
};
75 CFDictionaryRef csr_parameters
= CFDictionaryCreate(kCFAllocatorDefault
,
76 key
, val
, array_size(key
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
78 SecATV cn_phone
[] = { { kSecOidCommonName
, SecASN1PrintableString
, CFSTR("My iPhone") }, {} };
79 SecATV c
[] = { { kSecOidCountryName
, SecASN1PrintableString
, CFSTR("US") }, {} };
80 SecATV st
[] = { { kSecOidStateProvinceName
, SecASN1PrintableString
, CFSTR("CA") }, {} };
81 SecATV l
[] = { { kSecOidLocalityName
, SecASN1PrintableString
, CFSTR("Cupertino") }, {} };
82 SecATV o
[] = { { CFSTR("2.5.4.10"), SecASN1PrintableString
, CFSTR("Apple Inc.") }, {} };
83 SecATV ou
[] = { { kSecOidOrganizationalUnit
, SecASN1PrintableString
, CFSTR("iPhone") }, {} };
85 SecRDN atvs_phone
[] = { cn_phone
, c
, st
, l
, o
, ou
, NULL
};
87 ok_status(SecKeyGeneratePair(parameters
, &phone_publicKey
, &phone_privateKey
), "generate key pair");
88 ok_status(SecKeyGeneratePair(parameters
, &ca_publicKey
, &ca_privateKey
), "generate key pair");
90 int self_key_usage
= kSecKeyUsageKeyCertSign
| kSecKeyUsageCRLSign
;
91 CFNumberRef self_key_usage_num
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &self_key_usage
);
93 CFNumberRef path_len_num
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &path_len
);
94 const void *self_key
[] = { kSecCertificateKeyUsage
, kSecCSRBasicContraintsPathLen
};
95 const void *self_val
[] = { self_key_usage_num
, path_len_num
};
96 CFDictionaryRef self_signed_parameters
= CFDictionaryCreate(kCFAllocatorDefault
,
97 self_key
, self_val
, array_size(self_key
), NULL
, NULL
);
99 const void * ca_o
[] = { kSecOidOrganization
, CFSTR("Apple Inc.") };
100 const void * ca_cn
[] = { kSecOidCommonName
, CFSTR("Root CA") };
101 CFArrayRef ca_o_dn
= CFArrayCreate(kCFAllocatorDefault
, ca_o
, 2, NULL
);
102 CFArrayRef ca_cn_dn
= CFArrayCreate(kCFAllocatorDefault
, ca_cn
, 2, NULL
);
103 const void *ca_dn_array
[2];
104 ca_dn_array
[0] = CFArrayCreate(kCFAllocatorDefault
, (const void **)&ca_o_dn
, 1, NULL
);
105 ca_dn_array
[1] = CFArrayCreate(kCFAllocatorDefault
, (const void **)&ca_cn_dn
, 1, NULL
);
106 CFArrayRef ca_rdns
= CFArrayCreate(kCFAllocatorDefault
, ca_dn_array
, 2, NULL
);
108 SecCertificateRef ca_cert
= SecGenerateSelfSignedCertificate(ca_rdns
,
109 self_signed_parameters
, ca_publicKey
, ca_privateKey
);
110 SecCertificateRef ca_cert_phone_key
=
111 SecGenerateSelfSignedCertificate(ca_rdns
, self_signed_parameters
, phone_publicKey
, phone_privateKey
);
113 CFReleaseSafe(self_signed_parameters
);
114 CFReleaseSafe(self_key_usage_num
);
115 CFReleaseSafe(path_len_num
);
116 CFReleaseNull(ca_o_dn
);
117 CFReleaseNull(ca_cn_dn
);
118 CFReleaseNull(ca_dn_array
[0]);
119 CFReleaseNull(ca_dn_array
[1]);
120 CFReleaseNull(ca_rdns
);
122 isnt(ca_cert
, NULL
, "got back a cert");
123 ok(SecCertificateIsSelfSignedCA(ca_cert
), "cert is self-signed ca cert");
124 isnt(ca_cert_phone_key
, NULL
, "got back a cert");
125 ok(SecCertificateIsSelfSignedCA(ca_cert_phone_key
), "cert is self-signed ca cert");
126 CFDataRef data
= SecCertificateCopyData(ca_cert
);
127 //write_data("/tmp/ca_cert.der", data);
130 SecIdentityRef ca_identity
= SecIdentityCreate(kCFAllocatorDefault
, ca_cert
, ca_privateKey
);
131 SecIdentityRef ca_identity_phone_key
= SecIdentityCreate(kCFAllocatorDefault
, ca_cert_phone_key
, phone_privateKey
);
132 isnt(ca_identity
, NULL
, "got a identity");
133 isnt(ca_identity_phone_key
, NULL
, "got a identity");
134 CFDictionaryRef dict
= CFDictionaryCreate(NULL
, (const void **)&kSecValueRef
, (const void **)&ca_identity
, 1, NULL
, NULL
);
135 ok_status(SecItemAdd(dict
, NULL
), "add ca identity");
139 todo("Adding a cert with the same issuer/serial but a different key should return something other than errSecDuplicateItem");
143 dict
= CFDictionaryCreate(NULL
, (const void **)&kSecValueRef
, (const void **)&ca_identity_phone_key
, 1, NULL
, NULL
);
144 is_status(errSecDuplicateItem
, SecItemAdd(dict
, NULL
), "add ca identity");
148 CFDataRef csr
= SecGenerateCertificateRequestWithParameters(atvs_phone
, NULL
, phone_publicKey
, phone_privateKey
);
149 isnt(csr
, NULL
, "got back a csr");
152 //dict[kSecSubjectAltName, dict[ntPrincipalName, "foo@bar.org"]]
153 CFStringRef nt_princ_name_val
= CFSTR("foo@bar.org");
154 CFStringRef nt_princ_name_key
= CFSTR("ntPrincipalName");
155 CFDictionaryRef nt_princ
= CFDictionaryCreate(NULL
, (const void **)&nt_princ_name_key
, (const void **)&nt_princ_name_val
, 1, NULL
, NULL
);
156 CFDictionaryRef params
= CFDictionaryCreate(NULL
, (const void **)&kSecSubjectAltName
, (const void **)&nt_princ
, 1, NULL
, NULL
);
158 csr
= SecGenerateCertificateRequestWithParameters(atvs_phone
, params
, phone_publicKey
, phone_privateKey
);
159 isnt(csr
, NULL
, "got back a csr");
160 //write_data("/var/tmp/csr-nt-princ", csr);
162 CFReleaseNull(params
);
163 CFReleaseNull(nt_princ
);
165 csr
= SecGenerateCertificateRequestWithParameters(atvs_phone
, csr_parameters
, phone_publicKey
, phone_privateKey
);
166 isnt(csr
, NULL
, "csr w/ params");
167 //write_data("/tmp/csr", csr);
168 CFDataRef subject
, extensions
;
169 CFStringRef challenge
;
170 ok(SecVerifyCertificateRequest(csr
, NULL
, &challenge
, &subject
, &extensions
), "verify csr");
173 uint8_t serialno_byte
= 42;
174 CFDataRef serialno
= CFDataCreate(kCFAllocatorDefault
, &serialno_byte
, sizeof(serialno_byte
));
175 SecCertificateRef cert
= SecIdentitySignCertificate(ca_identity
, serialno
,
176 phone_publicKey
, subject
, extensions
);
177 data
= SecCertificateCopyData(cert
);
178 //write_data("/tmp/iphone_cert.der", data);
180 CFReleaseNull(subject
);
181 CFReleaseNull(extensions
);
182 CFReleaseNull(challenge
);
184 const void * email
[] = { CFSTR("1.2.840.113549.1.9.1"), CFSTR("foo@bar.biz") };
185 const void * cn
[] = { CFSTR("2.5.4.3"), CFSTR("S/MIME Baby") };
186 CFArrayRef email_dn
= CFArrayCreate(kCFAllocatorDefault
, email
, 2, NULL
);
187 CFArrayRef cn_dn
= CFArrayCreate(kCFAllocatorDefault
, cn
, 2, NULL
);
188 const void *dn_array
[2];
189 dn_array
[0] = CFArrayCreate(kCFAllocatorDefault
, (const void **)&email_dn
, 1, NULL
);
190 dn_array
[1] = CFArrayCreate(kCFAllocatorDefault
, (const void **)&cn_dn
, 1, NULL
);
191 CFArrayRef rdns
= CFArrayCreate(kCFAllocatorDefault
, dn_array
, 2, NULL
);
192 CFDictionarySetValue(subject_alt_names
, CFSTR("rfc822name"), CFSTR("mongo@pawn.org"));
194 uint8_t random_extension_data
[] = { 0xde, 0xad, 0xbe, 0xef };
195 CFDataRef random_extension_value
= CFDataCreate(kCFAllocatorDefault
, random_extension_data
, sizeof(random_extension_data
));
196 CFDictionarySetValue(random_extensions
, CFSTR("1.2.840.113635.100.6.1.2"), random_extension_value
); // APPLE_FDR_ACCESS_OID
197 CFDictionarySetValue(random_extensions
, CFSTR("1.2.840.113635.100.6.1.3"), CFSTR("that guy")); // APPLE_FDR_CLIENT_IDENTIFIER_OID
198 CFReleaseNull(random_extension_value
);
200 csr
= SecGenerateCertificateRequest(rdns
, csr_parameters
, phone_publicKey
, phone_privateKey
);
201 isnt(csr
, NULL
, "csr w/ params");
202 //write_data("/tmp/csr_neu", csr);
204 CFReleaseNull(subject_alt_names
);
205 CFDictionaryRemoveAllValues(random_extensions
);
208 CFDataRef scep_request
= SecSCEPGenerateCertificateRequest(rdns
,
209 csr_parameters
, phone_publicKey
, phone_privateKey
, NULL
, ca_cert
);
210 isnt(scep_request
, NULL
, "got scep blob");
211 //write_data("/tmp/scep_request.der", scep_request);
214 CFReleaseNull(email_dn
);
215 CFReleaseNull(cn_dn
);
216 CFReleaseNull(dn_array
[0]);
217 CFReleaseNull(dn_array
[1]);
221 CFDataRef scep_reply
= SecSCEPCertifyRequest(scep_request
, ca_identity
, serialno
, false);
222 isnt(scep_reply
, NULL
, "produced scep reply");
223 //write_data("/tmp/scep_reply.der", scep_reply);
225 CFArrayRef issued_certs
= NULL
;
226 ok(issued_certs
= SecSCEPVerifyReply(scep_request
, scep_reply
, ca_cert
, NULL
), "verify scep reply");
228 // take the issued cert and CA cert and pretend it's a RA/CA couple
229 CFMutableArrayRef scep_certs
= CFArrayCreateMutableCopy(kCFAllocatorDefault
, 0, issued_certs
);
230 CFArrayAppendValue(scep_certs
, ca_cert
);
231 SecCertificateRef ca_certificate
= NULL
, ra_signing_certificate
= NULL
, ra_encryption_certificate
= NULL
;
233 ok_status(SecSCEPValidateCACertMessage(scep_certs
, NULL
,
234 &ca_certificate
, &ra_signing_certificate
,
235 &ra_encryption_certificate
), "pull apart array again");
236 ok(CFEqual(ca_cert
, ca_certificate
), "found ca");
237 ok(CFArrayContainsValue(issued_certs
, CFRangeMake(0, CFArrayGetCount(issued_certs
)), ra_signing_certificate
), "found ra");
238 ok(!ra_encryption_certificate
, "no separate encryption cert");
240 CFReleaseSafe(ca_certificate
);
241 CFReleaseSafe(ra_signing_certificate
);
242 CFReleaseSafe(scep_certs
);
244 CFReleaseSafe(scep_request
);
245 CFReleaseSafe(scep_reply
);
246 CFReleaseSafe(issued_certs
);
250 dict
= CFDictionaryCreate(NULL
, (const void **)&kSecValueRef
, (const void **)&ca_identity
, 1, NULL
, NULL
);
251 ok_status(SecItemDelete(dict
), "delete ca identity");
253 dict
= CFDictionaryCreate(NULL
, (const void **)&kSecValueRef
, (const void **)&phone_privateKey
, 1, NULL
, NULL
);
254 ok_status(SecItemDelete(dict
), "delete phone private key");
257 CFReleaseSafe(serialno
);
260 CFReleaseSafe(ca_identity
);
261 CFReleaseSafe(ca_cert
);
262 CFReleaseSafe(ca_identity_phone_key
);
263 CFReleaseSafe(ca_cert_phone_key
);
264 CFReleaseSafe(csr_parameters
);
265 CFReleaseSafe(random_extensions
);
266 CFReleaseSafe(parameters
);
267 CFReleaseSafe(ca_publicKey
);
268 CFReleaseSafe(ca_privateKey
);
269 CFReleaseSafe(phone_publicKey
);
270 CFReleaseSafe(phone_privateKey
);
273 static void test_ec_csr(void) {
274 SecKeyRef ecPublicKey
= NULL
, ecPrivateKey
= NULL
;
277 CFNumberRef key_size_num
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &keysize
);
279 const void *keyParamsKeys
[] = { kSecAttrKeyType
, kSecAttrKeySizeInBits
};
280 const void *keyParamsValues
[] = { kSecAttrKeyTypeECSECPrimeRandom
, key_size_num
};
281 CFDictionaryRef keyParameters
= CFDictionaryCreate(NULL
, keyParamsKeys
, keyParamsValues
, 2,
282 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
283 ok_status(SecKeyGeneratePair(keyParameters
, &ecPublicKey
, &ecPrivateKey
),
284 "unable to generate EC key");
286 SecATV cn_phone
[] = { { kSecOidCommonName
, SecASN1PrintableString
, CFSTR("My iPhone") }, {} };
287 SecATV c
[] = { { kSecOidCountryName
, SecASN1PrintableString
, CFSTR("US") }, {} };
288 SecATV st
[] = { { kSecOidStateProvinceName
, SecASN1PrintableString
, CFSTR("CA") }, {} };
289 SecATV l
[] = { { kSecOidLocalityName
, SecASN1PrintableString
, CFSTR("Cupertino") }, {} };
290 SecATV o
[] = { { CFSTR("2.5.4.10"), SecASN1PrintableString
, CFSTR("Apple Inc.") }, {} };
291 SecATV ou
[] = { { kSecOidOrganizationalUnit
, SecASN1PrintableString
, CFSTR("iPhone") }, {} };
293 SecRDN atvs_phone
[] = { cn_phone
, c
, st
, l
, o
, ou
, NULL
};
295 CFMutableDictionaryRef subject_alt_names
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
296 CFDictionarySetValue(subject_alt_names
, CFSTR("dnsname"), CFSTR("xey.nl"));
298 int key_usage
= kSecKeyUsageDigitalSignature
| kSecKeyUsageKeyEncipherment
;
299 CFNumberRef key_usage_num
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &key_usage
);
301 CFMutableDictionaryRef random_extensions
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
303 const void *key
[] = { kSecCSRChallengePassword
, kSecSubjectAltName
, kSecCertificateKeyUsage
, kSecCertificateExtensions
};
304 const void *val
[] = { CFSTR("magic"), subject_alt_names
, key_usage_num
, random_extensions
};
305 CFDictionaryRef csr_parameters
= CFDictionaryCreate(kCFAllocatorDefault
,
306 key
, val
, array_size(key
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
309 CFDataRef csr
= SecGenerateCertificateRequestWithParameters(atvs_phone
, csr_parameters
, ecPublicKey
, ecPrivateKey
);
310 isnt(csr
, NULL
, "csr w/ params");
311 //write_data("/tmp/csr", csr);
312 CFDataRef subject
, extensions
;
313 CFStringRef challenge
;
314 ok(SecVerifyCertificateRequest(csr
, NULL
, &challenge
, &subject
, &extensions
), "verify csr");
317 CFReleaseNull(key_size_num
);
318 CFReleaseNull(keyParameters
);
319 CFReleaseNull(ecPublicKey
);
320 CFReleaseNull(ecPrivateKey
);
321 CFReleaseNull(subject_alt_names
);
322 CFReleaseNull(key_usage_num
);
323 CFReleaseNull(random_extensions
);
324 CFReleaseNull(csr_parameters
);
325 CFReleaseNull(subject
);
326 CFReleaseNull(extensions
);
327 CFReleaseNull(challenge
);
330 int si_62_csr(int argc
, char *const *argv
)