1/* 2 * si-62-csr.c 3 * Security 4 * 5 * Created by Conrad Sauerwald on 5/7/08. 6 * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. 7 * 8 */ 9 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> 19 20#include <Security/SecInternal.h> 21#include <CoreFoundation/CoreFoundation.h> 22#include <stdlib.h> 23#include <unistd.h> 24 25#include "Security_regressions.h" 26 27#include <fcntl.h> 28static inline void write_data(const char * path, CFDataRef data) 29{ 30 int data_file = open(path, O_CREAT|O_WRONLY|O_TRUNC, 0644); 31 write(data_file, CFDataGetBytePtr(data), CFDataGetLength(data)); 32 close(data_file); 33} 34 35 36static void tests(void) 37{ 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 ); 45 46 47 CFMutableDictionaryRef subject_alt_names = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 48 CFDictionarySetValue(subject_alt_names, CFSTR("dnsname"), CFSTR("xey.nl")); 49 50 int key_usage = kSecKeyUsageDigitalSignature | kSecKeyUsageKeyEncipherment; 51 CFNumberRef key_usage_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &key_usage); 52 53 CFMutableDictionaryRef random_extensions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 54 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); 59 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") }, {} }; 66 67 SecRDN atvs_phone[] = { cn_phone, c, st, l, o, ou, NULL }; 68 69 ok_status(SecKeyGeneratePair(parameters, &phone_publicKey, &phone_privateKey), "generate key pair"); 70 ok_status(SecKeyGeneratePair(parameters, &ca_publicKey, &ca_privateKey), "generate key pair"); 71 72 int self_key_usage = kSecKeyUsageKeyCertSign | kSecKeyUsageCRLSign; 73 CFNumberRef self_key_usage_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &self_key_usage); 74 int path_len = 0; 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); 80 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); 89 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); 94 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); 103 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); 110 CFReleaseSafe(data); 111 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"); 118 CFReleaseSafe(dict); 119 TODO: { 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"); 123 CFReleaseSafe(dict); 124 } 125 126 CFDataRef csr = SecGenerateCertificateRequestWithParameters(atvs_phone, NULL, phone_publicKey, phone_privateKey); 127 isnt(csr, NULL, "got back a csr"); 128 CFReleaseNull(csr); 129 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); 135 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); 139 CFReleaseNull(csr); 140 CFReleaseNull(params); 141 CFReleaseNull(nt_princ); 142 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"); 149 CFReleaseNull(csr); 150 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); 157 CFReleaseNull(data); 158 CFReleaseNull(subject); 159 CFReleaseNull(extensions); 160 CFReleaseNull(challenge); 161 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")); 171 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); 177 178 csr = SecGenerateCertificateRequest(rdns, csr_parameters, phone_publicKey, phone_privateKey); 179 isnt(csr, NULL, "csr w/ params"); 180 //write_data("/tmp/csr_neu", csr); 181 CFReleaseNull(csr); 182 CFReleaseNull(subject_alt_names); 183 CFDictionaryRemoveAllValues(random_extensions); 184 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); 189 190 CFReleaseNull(email_dn); 191 CFReleaseNull(cn_dn); 192 CFReleaseNull(dn_array[0]); 193 CFReleaseNull(dn_array[1]); 194 CFReleaseNull(rdns); 195 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); 199 200 CFArrayRef issued_certs = NULL; 201 ok(issued_certs = SecSCEPVerifyReply(scep_request, scep_reply, ca_cert, NULL), "verify scep reply"); 202 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; 207 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"); 214 215 // cleanups 216 dict = CFDictionaryCreate(NULL, &kSecValueRef, (const void **)&ca_identity, 1, NULL, NULL); 217 ok_status(SecItemDelete(dict), "delete ca identity"); 218 CFReleaseSafe(dict); 219 dict = CFDictionaryCreate(NULL, &kSecValueRef, (const void **)&phone_privateKey, 1, NULL, NULL); 220 ok_status(SecItemDelete(dict), "delete phone private key"); 221 CFReleaseSafe(dict); 222 223 224 CFReleaseSafe(ca_certificate); 225 CFReleaseSafe(ra_signing_certificate); 226 CFReleaseSafe(scep_certs); 227 228 CFReleaseSafe(scep_request); 229 CFReleaseSafe(scep_reply); 230 CFReleaseSafe(issued_certs); 231 CFReleaseSafe(serialno); 232 233 CFReleaseSafe(cert); 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); 245} 246 247int si_62_csr(int argc, char *const *argv) 248{ 249 plan_tests(24); 250 251 252 tests(); 253 254 return 0; 255} 256