5 * Created by Conrad Sauerwald on 5/7/08.
6 * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved.
10 #include <Security/SecKey.h>
11 #include <Security/SecItem.h>
12 #include <Security/SecItemPriv.h>
13 #include <Security/SecCMS.h>
14 #include <Security/SecCertificateRequest.h>
15 #include <Security/SecSCEP.h>
16 #include <Security/SecCertificatePriv.h>
17 #include <Security/SecIdentityPriv.h>
18 #include <utilities/array_size.h>
20 #include <Security/SecInternal.h>
21 #include <CoreFoundation/CoreFoundation.h>
25 #include "Security_regressions.h"
28 static inline void write_data(const char * path
, CFDataRef data
)
30 int data_file
= open(path
, O_CREAT
|O_WRONLY
|O_TRUNC
, 0644);
31 write(data_file
, CFDataGetBytePtr(data
), CFDataGetLength(data
));
36 static void tests(void)
38 SecKeyRef phone_publicKey
= NULL
, phone_privateKey
= NULL
;
39 SecKeyRef ca_publicKey
= NULL
, ca_privateKey
= NULL
;
40 const void *keygen_keys
[] = { kSecAttrKeyType
, kSecAttrKeySizeInBits
};
41 const void *keygen_vals
[] = { kSecAttrKeyTypeRSA
, CFSTR("512") };
42 CFDictionaryRef parameters
= CFDictionaryCreate(kCFAllocatorDefault
,
43 keygen_keys
, keygen_vals
, array_size(keygen_vals
),
44 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
47 CFMutableDictionaryRef subject_alt_names
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
48 CFDictionarySetValue(subject_alt_names
, CFSTR("dnsname"), CFSTR("xey.nl"));
50 int key_usage
= kSecKeyUsageDigitalSignature
| kSecKeyUsageKeyEncipherment
;
51 CFNumberRef key_usage_num
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &key_usage
);
53 CFMutableDictionaryRef random_extensions
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
55 const void *key
[] = { kSecCSRChallengePassword
, kSecSubjectAltName
, kSecCertificateKeyUsage
, kSecCertificateExtensions
};
56 const void *val
[] = { CFSTR("magic"), subject_alt_names
, key_usage_num
, random_extensions
};
57 CFDictionaryRef csr_parameters
= CFDictionaryCreate(kCFAllocatorDefault
,
58 key
, val
, array_size(key
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
60 SecATV cn_phone
[] = { { kSecOidCommonName
, SecASN1PrintableString
, CFSTR("My iPhone") }, {} };
61 SecATV c
[] = { { kSecOidCountryName
, SecASN1PrintableString
, CFSTR("US") }, {} };
62 SecATV st
[] = { { kSecOidStateProvinceName
, SecASN1PrintableString
, CFSTR("CA") }, {} };
63 SecATV l
[] = { { kSecOidLocalityName
, SecASN1PrintableString
, CFSTR("Cupertino") }, {} };
64 SecATV o
[] = { { CFSTR("2.5.4.10"), SecASN1PrintableString
, CFSTR("Apple Inc.") }, {} };
65 SecATV ou
[] = { { kSecOidOrganizationalUnit
, SecASN1PrintableString
, CFSTR("iPhone") }, {} };
67 SecRDN atvs_phone
[] = { cn_phone
, c
, st
, l
, o
, ou
, NULL
};
69 ok_status(SecKeyGeneratePair(parameters
, &phone_publicKey
, &phone_privateKey
), "generate key pair");
70 ok_status(SecKeyGeneratePair(parameters
, &ca_publicKey
, &ca_privateKey
), "generate key pair");
72 int self_key_usage
= kSecKeyUsageKeyCertSign
| kSecKeyUsageCRLSign
;
73 CFNumberRef self_key_usage_num
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &self_key_usage
);
75 CFNumberRef path_len_num
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &path_len
);
76 const void *self_key
[] = { kSecCertificateKeyUsage
, kSecCSRBasicContraintsPathLen
};
77 const void *self_val
[] = { self_key_usage_num
, path_len_num
};
78 CFDictionaryRef self_signed_parameters
= CFDictionaryCreate(kCFAllocatorDefault
,
79 self_key
, self_val
, array_size(self_key
), NULL
, NULL
);
81 const void * ca_o
[] = { kSecOidOrganization
, CFSTR("Apple Inc.") };
82 const void * ca_cn
[] = { kSecOidCommonName
, CFSTR("Root CA") };
83 CFArrayRef ca_o_dn
= CFArrayCreate(kCFAllocatorDefault
, ca_o
, 2, NULL
);
84 CFArrayRef ca_cn_dn
= CFArrayCreate(kCFAllocatorDefault
, ca_cn
, 2, NULL
);
85 const void *ca_dn_array
[2];
86 ca_dn_array
[0] = CFArrayCreate(kCFAllocatorDefault
, (const void **)&ca_o_dn
, 1, NULL
);
87 ca_dn_array
[1] = CFArrayCreate(kCFAllocatorDefault
, (const void **)&ca_cn_dn
, 1, NULL
);
88 CFArrayRef ca_rdns
= CFArrayCreate(kCFAllocatorDefault
, ca_dn_array
, 2, NULL
);
90 SecCertificateRef ca_cert
= SecGenerateSelfSignedCertificate(ca_rdns
,
91 self_signed_parameters
, ca_publicKey
, ca_privateKey
);
92 SecCertificateRef ca_cert_phone_key
=
93 SecGenerateSelfSignedCertificate(ca_rdns
, self_signed_parameters
, phone_publicKey
, phone_privateKey
);
95 CFReleaseSafe(self_signed_parameters
);
96 CFReleaseSafe(self_key_usage_num
);
97 CFReleaseSafe(path_len_num
);
98 CFReleaseNull(ca_o_dn
);
99 CFReleaseNull(ca_cn_dn
);
100 CFReleaseNull(ca_dn_array
[0]);
101 CFReleaseNull(ca_dn_array
[1]);
102 CFReleaseNull(ca_rdns
);
104 isnt(ca_cert
, NULL
, "got back a cert");
105 ok(SecCertificateIsSelfSignedCA(ca_cert
), "cert is self-signed ca cert");
106 isnt(ca_cert_phone_key
, NULL
, "got back a cert");
107 ok(SecCertificateIsSelfSignedCA(ca_cert_phone_key
), "cert is self-signed ca cert");
108 CFDataRef data
= SecCertificateCopyData(ca_cert
);
109 //write_data("/tmp/ca_cert.der", data);
112 SecIdentityRef ca_identity
= SecIdentityCreate(kCFAllocatorDefault
, ca_cert
, ca_privateKey
);
113 SecIdentityRef ca_identity_phone_key
= SecIdentityCreate(kCFAllocatorDefault
, ca_cert_phone_key
, phone_privateKey
);
114 isnt(ca_identity
, NULL
, "got a identity");
115 isnt(ca_identity_phone_key
, NULL
, "got a identity");
116 CFDictionaryRef dict
= CFDictionaryCreate(NULL
, &kSecValueRef
, (const void **)&ca_identity
, 1, NULL
, NULL
);
117 ok_status(SecItemAdd(dict
, NULL
), "add ca identity");
120 todo("Adding a cert with the same issuer/serial but a different key should return something other than errSecDuplicateItem");
121 dict
= CFDictionaryCreate(NULL
, &kSecValueRef
, (const void **)&ca_identity_phone_key
, 1, NULL
, NULL
);
122 is_status(errSecDuplicateItem
, SecItemAdd(dict
, NULL
), "add ca identity");
126 CFDataRef csr
= SecGenerateCertificateRequestWithParameters(atvs_phone
, NULL
, phone_publicKey
, phone_privateKey
);
127 isnt(csr
, NULL
, "got back a csr");
130 //dict[kSecSubjectAltName, dict[ntPrincipalName, "foo@bar.org"]]
131 CFStringRef nt_princ_name_val
= CFSTR("foo@bar.org");
132 CFStringRef nt_princ_name_key
= CFSTR("ntPrincipalName");
133 CFDictionaryRef nt_princ
= CFDictionaryCreate(NULL
, (const void **)&nt_princ_name_key
, (const void **)&nt_princ_name_val
, 1, NULL
, NULL
);
134 CFDictionaryRef params
= CFDictionaryCreate(NULL
, &kSecSubjectAltName
, (const void **)&nt_princ
, 1, NULL
, NULL
);
136 csr
= SecGenerateCertificateRequestWithParameters(atvs_phone
, params
, phone_publicKey
, phone_privateKey
);
137 isnt(csr
, NULL
, "got back a csr");
138 //write_data("/var/tmp/csr-nt-princ", csr);
140 CFReleaseNull(params
);
141 CFReleaseNull(nt_princ
);
143 csr
= SecGenerateCertificateRequestWithParameters(atvs_phone
, csr_parameters
, phone_publicKey
, phone_privateKey
);
144 isnt(csr
, NULL
, "csr w/ params");
145 //write_data("/tmp/csr", csr);
146 CFDataRef subject
, extensions
;
147 CFStringRef challenge
;
148 ok(SecVerifyCertificateRequest(csr
, NULL
, &challenge
, &subject
, &extensions
), "verify csr");
151 uint8_t serialno_byte
= 42;
152 CFDataRef serialno
= CFDataCreate(kCFAllocatorDefault
, &serialno_byte
, sizeof(serialno_byte
));
153 SecCertificateRef cert
= SecIdentitySignCertificate(ca_identity
, serialno
,
154 phone_publicKey
, subject
, extensions
);
155 data
= SecCertificateCopyData(cert
);
156 //write_data("/tmp/iphone_cert.der", data);
158 CFReleaseNull(subject
);
159 CFReleaseNull(extensions
);
160 CFReleaseNull(challenge
);
162 const void * email
[] = { CFSTR("1.2.840.113549.1.9.1"), CFSTR("foo@bar.biz") };
163 const void * cn
[] = { CFSTR("2.5.4.3"), CFSTR("S/MIME Baby") };
164 CFArrayRef email_dn
= CFArrayCreate(kCFAllocatorDefault
, email
, 2, NULL
);
165 CFArrayRef cn_dn
= CFArrayCreate(kCFAllocatorDefault
, cn
, 2, NULL
);
166 const void *dn_array
[2];
167 dn_array
[0] = CFArrayCreate(kCFAllocatorDefault
, (const void **)&email_dn
, 1, NULL
);
168 dn_array
[1] = CFArrayCreate(kCFAllocatorDefault
, (const void **)&cn_dn
, 1, NULL
);
169 CFArrayRef rdns
= CFArrayCreate(kCFAllocatorDefault
, dn_array
, 2, NULL
);
170 CFDictionarySetValue(subject_alt_names
, CFSTR("rfc822name"), CFSTR("mongo@pawn.org"));
172 uint8_t random_extension_data
[] = { 0xde, 0xad, 0xbe, 0xef };
173 CFDataRef random_extension_value
= CFDataCreate(kCFAllocatorDefault
, random_extension_data
, sizeof(random_extension_data
));
174 CFDictionarySetValue(random_extensions
, CFSTR("1.2.840.113635.100.6.1.2"), random_extension_value
); // APPLE_FDR_ACCESS_OID
175 CFDictionarySetValue(random_extensions
, CFSTR("1.2.840.113635.100.6.1.3"), CFSTR("that guy")); // APPLE_FDR_CLIENT_IDENTIFIER_OID
176 CFReleaseNull(random_extension_value
);
178 csr
= SecGenerateCertificateRequest(rdns
, csr_parameters
, phone_publicKey
, phone_privateKey
);
179 isnt(csr
, NULL
, "csr w/ params");
180 //write_data("/tmp/csr_neu", csr);
182 CFReleaseNull(subject_alt_names
);
183 CFDictionaryRemoveAllValues(random_extensions
);
185 CFDataRef scep_request
= SecSCEPGenerateCertificateRequest(rdns
,
186 csr_parameters
, phone_publicKey
, phone_privateKey
, NULL
, ca_cert
);
187 isnt(scep_request
, NULL
, "got scep blob");
188 //write_data("/tmp/scep_request.der", scep_request);
190 CFReleaseNull(email_dn
);
191 CFReleaseNull(cn_dn
);
192 CFReleaseNull(dn_array
[0]);
193 CFReleaseNull(dn_array
[1]);
196 CFDataRef scep_reply
= SecSCEPCertifyRequest(scep_request
, ca_identity
, serialno
, false);
197 isnt(scep_reply
, NULL
, "produced scep reply");
198 //write_data("/tmp/scep_reply.der", scep_reply);
200 CFArrayRef issued_certs
= NULL
;
201 ok(issued_certs
= SecSCEPVerifyReply(scep_request
, scep_reply
, ca_cert
, NULL
), "verify scep reply");
203 // take the issued cert and CA cert and pretend it's a RA/CA couple
204 CFMutableArrayRef scep_certs
= CFArrayCreateMutableCopy(kCFAllocatorDefault
, 0, issued_certs
);
205 CFArrayAppendValue(scep_certs
, ca_cert
);
206 SecCertificateRef ca_certificate
= NULL
, ra_signing_certificate
= NULL
, ra_encryption_certificate
= NULL
;
208 ok_status(SecSCEPValidateCACertMessage(scep_certs
, NULL
,
209 &ca_certificate
, &ra_signing_certificate
,
210 &ra_encryption_certificate
), "pull apart array again");
211 ok(CFEqual(ca_cert
, ca_certificate
), "found ca");
212 ok(CFArrayContainsValue(issued_certs
, CFRangeMake(0, CFArrayGetCount(issued_certs
)), ra_signing_certificate
), "found ra");
213 ok(!ra_encryption_certificate
, "no separate encryption cert");
216 dict
= CFDictionaryCreate(NULL
, &kSecValueRef
, (const void **)&ca_identity
, 1, NULL
, NULL
);
217 ok_status(SecItemDelete(dict
), "delete ca identity");
219 dict
= CFDictionaryCreate(NULL
, &kSecValueRef
, (const void **)&phone_privateKey
, 1, NULL
, NULL
);
220 ok_status(SecItemDelete(dict
), "delete phone private key");
224 CFReleaseSafe(ca_certificate
);
225 CFReleaseSafe(ra_signing_certificate
);
226 CFReleaseSafe(scep_certs
);
228 CFReleaseSafe(scep_request
);
229 CFReleaseSafe(scep_reply
);
230 CFReleaseSafe(issued_certs
);
231 CFReleaseSafe(serialno
);
234 CFReleaseSafe(ca_identity
);
235 CFReleaseSafe(ca_cert
);
236 CFReleaseSafe(ca_identity_phone_key
);
237 CFReleaseSafe(ca_cert_phone_key
);
238 CFReleaseSafe(csr_parameters
);
239 CFReleaseSafe(random_extensions
);
240 CFReleaseSafe(parameters
);
241 CFReleaseSafe(ca_publicKey
);
242 CFReleaseSafe(ca_privateKey
);
243 CFReleaseSafe(phone_publicKey
);
244 CFReleaseSafe(phone_privateKey
);
247 int si_62_csr(int argc
, char *const *argv
)