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 "Security_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
;
55 const void *keygen_keys
[] = { kSecAttrKeyType
, kSecAttrKeySizeInBits
};
56 const void *keygen_vals
[] = { kSecAttrKeyTypeRSA
, CFSTR("512") };
57 CFDictionaryRef parameters
= CFDictionaryCreate(kCFAllocatorDefault
,
58 keygen_keys
, keygen_vals
, array_size(keygen_vals
),
59 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
62 CFMutableDictionaryRef subject_alt_names
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
63 CFDictionarySetValue(subject_alt_names
, CFSTR("dnsname"), CFSTR("xey.nl"));
65 int key_usage
= kSecKeyUsageDigitalSignature
| kSecKeyUsageKeyEncipherment
;
66 CFNumberRef key_usage_num
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &key_usage
);
68 CFMutableDictionaryRef random_extensions
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
70 const void *key
[] = { kSecCSRChallengePassword
, kSecSubjectAltName
, kSecCertificateKeyUsage
, kSecCertificateExtensions
};
71 const void *val
[] = { CFSTR("magic"), subject_alt_names
, key_usage_num
, random_extensions
};
72 CFDictionaryRef csr_parameters
= CFDictionaryCreate(kCFAllocatorDefault
,
73 key
, val
, array_size(key
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
75 SecATV cn_phone
[] = { { kSecOidCommonName
, SecASN1PrintableString
, CFSTR("My iPhone") }, {} };
76 SecATV c
[] = { { kSecOidCountryName
, SecASN1PrintableString
, CFSTR("US") }, {} };
77 SecATV st
[] = { { kSecOidStateProvinceName
, SecASN1PrintableString
, CFSTR("CA") }, {} };
78 SecATV l
[] = { { kSecOidLocalityName
, SecASN1PrintableString
, CFSTR("Cupertino") }, {} };
79 SecATV o
[] = { { CFSTR("2.5.4.10"), SecASN1PrintableString
, CFSTR("Apple Inc.") }, {} };
80 SecATV ou
[] = { { kSecOidOrganizationalUnit
, SecASN1PrintableString
, CFSTR("iPhone") }, {} };
82 SecRDN atvs_phone
[] = { cn_phone
, c
, st
, l
, o
, ou
, NULL
};
84 ok_status(SecKeyGeneratePair(parameters
, &phone_publicKey
, &phone_privateKey
), "generate key pair");
85 ok_status(SecKeyGeneratePair(parameters
, &ca_publicKey
, &ca_privateKey
), "generate key pair");
87 int self_key_usage
= kSecKeyUsageKeyCertSign
| kSecKeyUsageCRLSign
;
88 CFNumberRef self_key_usage_num
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &self_key_usage
);
90 CFNumberRef path_len_num
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &path_len
);
91 const void *self_key
[] = { kSecCertificateKeyUsage
, kSecCSRBasicContraintsPathLen
};
92 const void *self_val
[] = { self_key_usage_num
, path_len_num
};
93 CFDictionaryRef self_signed_parameters
= CFDictionaryCreate(kCFAllocatorDefault
,
94 self_key
, self_val
, array_size(self_key
), NULL
, NULL
);
96 const void * ca_o
[] = { kSecOidOrganization
, CFSTR("Apple Inc.") };
97 const void * ca_cn
[] = { kSecOidCommonName
, CFSTR("Root CA") };
98 CFArrayRef ca_o_dn
= CFArrayCreate(kCFAllocatorDefault
, ca_o
, 2, NULL
);
99 CFArrayRef ca_cn_dn
= CFArrayCreate(kCFAllocatorDefault
, ca_cn
, 2, NULL
);
100 const void *ca_dn_array
[2];
101 ca_dn_array
[0] = CFArrayCreate(kCFAllocatorDefault
, (const void **)&ca_o_dn
, 1, NULL
);
102 ca_dn_array
[1] = CFArrayCreate(kCFAllocatorDefault
, (const void **)&ca_cn_dn
, 1, NULL
);
103 CFArrayRef ca_rdns
= CFArrayCreate(kCFAllocatorDefault
, ca_dn_array
, 2, NULL
);
105 SecCertificateRef ca_cert
= SecGenerateSelfSignedCertificate(ca_rdns
,
106 self_signed_parameters
, ca_publicKey
, ca_privateKey
);
107 SecCertificateRef ca_cert_phone_key
=
108 SecGenerateSelfSignedCertificate(ca_rdns
, self_signed_parameters
, phone_publicKey
, phone_privateKey
);
110 CFReleaseSafe(self_signed_parameters
);
111 CFReleaseSafe(self_key_usage_num
);
112 CFReleaseSafe(path_len_num
);
113 CFReleaseNull(ca_o_dn
);
114 CFReleaseNull(ca_cn_dn
);
115 CFReleaseNull(ca_dn_array
[0]);
116 CFReleaseNull(ca_dn_array
[1]);
117 CFReleaseNull(ca_rdns
);
119 isnt(ca_cert
, NULL
, "got back a cert");
120 ok(SecCertificateIsSelfSignedCA(ca_cert
), "cert is self-signed ca cert");
121 isnt(ca_cert_phone_key
, NULL
, "got back a cert");
122 ok(SecCertificateIsSelfSignedCA(ca_cert_phone_key
), "cert is self-signed ca cert");
123 CFDataRef data
= SecCertificateCopyData(ca_cert
);
124 //write_data("/tmp/ca_cert.der", data);
127 SecIdentityRef ca_identity
= SecIdentityCreate(kCFAllocatorDefault
, ca_cert
, ca_privateKey
);
128 SecIdentityRef ca_identity_phone_key
= SecIdentityCreate(kCFAllocatorDefault
, ca_cert_phone_key
, phone_privateKey
);
129 isnt(ca_identity
, NULL
, "got a identity");
130 isnt(ca_identity_phone_key
, NULL
, "got a identity");
131 CFDictionaryRef dict
= CFDictionaryCreate(NULL
, (const void **)&kSecValueRef
, (const void **)&ca_identity
, 1, NULL
, NULL
);
132 ok_status(SecItemAdd(dict
, NULL
), "add ca identity");
135 todo("Adding a cert with the same issuer/serial but a different key should return something other than errSecDuplicateItem");
136 dict
= CFDictionaryCreate(NULL
, (const void **)&kSecValueRef
, (const void **)&ca_identity_phone_key
, 1, NULL
, NULL
);
137 is_status(errSecDuplicateItem
, SecItemAdd(dict
, NULL
), "add ca identity");
141 CFDataRef csr
= SecGenerateCertificateRequestWithParameters(atvs_phone
, NULL
, phone_publicKey
, phone_privateKey
);
142 isnt(csr
, NULL
, "got back a csr");
145 //dict[kSecSubjectAltName, dict[ntPrincipalName, "foo@bar.org"]]
146 CFStringRef nt_princ_name_val
= CFSTR("foo@bar.org");
147 CFStringRef nt_princ_name_key
= CFSTR("ntPrincipalName");
148 CFDictionaryRef nt_princ
= CFDictionaryCreate(NULL
, (const void **)&nt_princ_name_key
, (const void **)&nt_princ_name_val
, 1, NULL
, NULL
);
149 CFDictionaryRef params
= CFDictionaryCreate(NULL
, (const void **)&kSecSubjectAltName
, (const void **)&nt_princ
, 1, NULL
, NULL
);
151 csr
= SecGenerateCertificateRequestWithParameters(atvs_phone
, params
, phone_publicKey
, phone_privateKey
);
152 isnt(csr
, NULL
, "got back a csr");
153 //write_data("/var/tmp/csr-nt-princ", csr);
155 CFReleaseNull(params
);
156 CFReleaseNull(nt_princ
);
158 csr
= SecGenerateCertificateRequestWithParameters(atvs_phone
, csr_parameters
, phone_publicKey
, phone_privateKey
);
159 isnt(csr
, NULL
, "csr w/ params");
160 //write_data("/tmp/csr", csr);
161 CFDataRef subject
, extensions
;
162 CFStringRef challenge
;
163 ok(SecVerifyCertificateRequest(csr
, NULL
, &challenge
, &subject
, &extensions
), "verify csr");
166 uint8_t serialno_byte
= 42;
167 CFDataRef serialno
= CFDataCreate(kCFAllocatorDefault
, &serialno_byte
, sizeof(serialno_byte
));
168 SecCertificateRef cert
= SecIdentitySignCertificate(ca_identity
, serialno
,
169 phone_publicKey
, subject
, extensions
);
170 data
= SecCertificateCopyData(cert
);
171 //write_data("/tmp/iphone_cert.der", data);
173 CFReleaseNull(subject
);
174 CFReleaseNull(extensions
);
175 CFReleaseNull(challenge
);
177 const void * email
[] = { CFSTR("1.2.840.113549.1.9.1"), CFSTR("foo@bar.biz") };
178 const void * cn
[] = { CFSTR("2.5.4.3"), CFSTR("S/MIME Baby") };
179 CFArrayRef email_dn
= CFArrayCreate(kCFAllocatorDefault
, email
, 2, NULL
);
180 CFArrayRef cn_dn
= CFArrayCreate(kCFAllocatorDefault
, cn
, 2, NULL
);
181 const void *dn_array
[2];
182 dn_array
[0] = CFArrayCreate(kCFAllocatorDefault
, (const void **)&email_dn
, 1, NULL
);
183 dn_array
[1] = CFArrayCreate(kCFAllocatorDefault
, (const void **)&cn_dn
, 1, NULL
);
184 CFArrayRef rdns
= CFArrayCreate(kCFAllocatorDefault
, dn_array
, 2, NULL
);
185 CFDictionarySetValue(subject_alt_names
, CFSTR("rfc822name"), CFSTR("mongo@pawn.org"));
187 uint8_t random_extension_data
[] = { 0xde, 0xad, 0xbe, 0xef };
188 CFDataRef random_extension_value
= CFDataCreate(kCFAllocatorDefault
, random_extension_data
, sizeof(random_extension_data
));
189 CFDictionarySetValue(random_extensions
, CFSTR("1.2.840.113635.100.6.1.2"), random_extension_value
); // APPLE_FDR_ACCESS_OID
190 CFDictionarySetValue(random_extensions
, CFSTR("1.2.840.113635.100.6.1.3"), CFSTR("that guy")); // APPLE_FDR_CLIENT_IDENTIFIER_OID
191 CFReleaseNull(random_extension_value
);
193 csr
= SecGenerateCertificateRequest(rdns
, csr_parameters
, phone_publicKey
, phone_privateKey
);
194 isnt(csr
, NULL
, "csr w/ params");
195 //write_data("/tmp/csr_neu", csr);
197 CFReleaseNull(subject_alt_names
);
198 CFDictionaryRemoveAllValues(random_extensions
);
200 CFDataRef scep_request
= SecSCEPGenerateCertificateRequest(rdns
,
201 csr_parameters
, phone_publicKey
, phone_privateKey
, NULL
, ca_cert
);
202 isnt(scep_request
, NULL
, "got scep blob");
203 //write_data("/tmp/scep_request.der", scep_request);
205 CFReleaseNull(email_dn
);
206 CFReleaseNull(cn_dn
);
207 CFReleaseNull(dn_array
[0]);
208 CFReleaseNull(dn_array
[1]);
211 CFDataRef scep_reply
= SecSCEPCertifyRequest(scep_request
, ca_identity
, serialno
, false);
212 isnt(scep_reply
, NULL
, "produced scep reply");
213 //write_data("/tmp/scep_reply.der", scep_reply);
215 CFArrayRef issued_certs
= NULL
;
216 ok(issued_certs
= SecSCEPVerifyReply(scep_request
, scep_reply
, ca_cert
, NULL
), "verify scep reply");
218 // take the issued cert and CA cert and pretend it's a RA/CA couple
219 CFMutableArrayRef scep_certs
= CFArrayCreateMutableCopy(kCFAllocatorDefault
, 0, issued_certs
);
220 CFArrayAppendValue(scep_certs
, ca_cert
);
221 SecCertificateRef ca_certificate
= NULL
, ra_signing_certificate
= NULL
, ra_encryption_certificate
= NULL
;
223 ok_status(SecSCEPValidateCACertMessage(scep_certs
, NULL
,
224 &ca_certificate
, &ra_signing_certificate
,
225 &ra_encryption_certificate
), "pull apart array again");
226 ok(CFEqual(ca_cert
, ca_certificate
), "found ca");
227 ok(CFArrayContainsValue(issued_certs
, CFRangeMake(0, CFArrayGetCount(issued_certs
)), ra_signing_certificate
), "found ra");
228 ok(!ra_encryption_certificate
, "no separate encryption cert");
231 dict
= CFDictionaryCreate(NULL
, (const void **)&kSecValueRef
, (const void **)&ca_identity
, 1, NULL
, NULL
);
232 ok_status(SecItemDelete(dict
), "delete ca identity");
234 dict
= CFDictionaryCreate(NULL
, (const void **)&kSecValueRef
, (const void **)&phone_privateKey
, 1, NULL
, NULL
);
235 ok_status(SecItemDelete(dict
), "delete phone private key");
239 CFReleaseSafe(ca_certificate
);
240 CFReleaseSafe(ra_signing_certificate
);
241 CFReleaseSafe(scep_certs
);
243 CFReleaseSafe(scep_request
);
244 CFReleaseSafe(scep_reply
);
245 CFReleaseSafe(issued_certs
);
246 CFReleaseSafe(serialno
);
249 CFReleaseSafe(ca_identity
);
250 CFReleaseSafe(ca_cert
);
251 CFReleaseSafe(ca_identity_phone_key
);
252 CFReleaseSafe(ca_cert_phone_key
);
253 CFReleaseSafe(csr_parameters
);
254 CFReleaseSafe(random_extensions
);
255 CFReleaseSafe(parameters
);
256 CFReleaseSafe(ca_publicKey
);
257 CFReleaseSafe(ca_privateKey
);
258 CFReleaseSafe(phone_publicKey
);
259 CFReleaseSafe(phone_privateKey
);
262 int si_62_csr(int argc
, char *const *argv
)