2 * Copyright (c) 2009,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@
26 #include <TargetConditionals.h>
30 #include <CoreFoundation/CoreFoundation.h>
31 #include <Security/SecIdentityPriv.h>
32 #include <Security/SecItem.h>
33 #include <Security/SecCertificateRequest.h>
34 #include <Security/SecInternal.h>
35 #include <utilities/array_size.h>
37 #include <AssertMacros.h>
41 static inline CF_RETURNS_RETAINED CFMutableArrayRef
maa(CFMutableArrayRef array CF_CONSUMED
, CFTypeRef a CF_CONSUMED
) {
42 CFMutableArrayRef ma
= array
;
44 ma
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
46 CFArrayAppendValue(ma
, a
);
54 CFArrayRef
test_cert_string_to_subject(CFStringRef subject
)
56 CFMutableArrayRef subject_array
= NULL
;
59 if (!CFStringGetCString(subject
, buffer
, sizeof(buffer
), kCFStringEncodingASCII
))
62 char *s
= buffer
, *e
= NULL
;
63 while ( (e
= strchr(s
, ',')) || (e
= strchr(s
, '\0')) ) {
66 if (*e
&& (*(e
-1) == '\\'))
69 while ((k
= strchr(s
, '=')) &&
71 if ( ((k
- s
) > 0) && ((e
- k
) > 1) ) {
72 CFStringRef key
= CFStringCreateWithBytes(kCFAllocatorDefault
, (uint8_t *)s
, k
- s
, kCFStringEncodingASCII
, false);
73 CFStringRef value
= CFStringCreateWithBytes(kCFAllocatorDefault
, (uint8_t *)k
+ 1, e
- k
- 1, kCFStringEncodingASCII
, false);
74 subject_array
= maa(subject_array
, maa(NULL
, maa(maa(NULL
, key
), value
)));
86 static void test_cert_key_usage(CFMutableDictionaryRef extensions_dict
, unsigned int key_usage
)
88 int key_usage_int
= key_usage
;
89 CFNumberRef key_usage_num
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &key_usage_int
);
90 CFDictionarySetValue(extensions_dict
, kSecCertificateKeyUsage
, key_usage_num
);
91 CFRelease(key_usage_num
);
95 static void test_cert_path_length(CFMutableDictionaryRef extensions_dict
, unsigned int path_length
)
97 int path_len_int
= path_length
;
98 CFNumberRef path_len_num
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &path_len_int
);
99 CFDictionarySetValue(extensions_dict
, kSecCSRBasicContraintsPathLen
, path_len_num
);
100 CFRelease(path_len_num
);
104 SecIdentityRef
test_cert_create_root_certificate(CFStringRef subject
, SecKeyRef public_key
, SecKeyRef private_key
)
106 SecCertificateRef ca_cert
= NULL
;
107 SecIdentityRef ca_identity
= NULL
;
108 CFMutableDictionaryRef extensions
= NULL
;
110 CFArrayRef ca_subject
= NULL
;
111 require(ca_subject
= test_cert_string_to_subject(subject
), out
);
112 extensions
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
113 test_cert_key_usage(extensions
, kSecKeyUsageKeyCertSign
| kSecKeyUsageCRLSign
);
114 test_cert_path_length(extensions
, 0);
115 ca_cert
= SecGenerateSelfSignedCertificate(ca_subject
, extensions
, public_key
, private_key
);
116 if (private_key
&& ca_cert
)
117 ca_identity
= SecIdentityCreate(kCFAllocatorDefault
, ca_cert
, private_key
);
120 CFReleaseSafe(extensions
);
121 CFReleaseSafe(ca_subject
);
122 CFReleaseSafe(ca_cert
);
127 SecCertificateRef
test_cert_issue_certificate(SecIdentityRef ca_identity
,
128 SecKeyRef public_key
, CFStringRef subject
,
129 unsigned int serial_no
, unsigned int key_usage
)
131 SecCertificateRef cert
= NULL
;
132 CFArrayRef cert_subject
= NULL
;
133 CFDataRef serialno
= NULL
;
134 CFMutableDictionaryRef extensions
= NULL
;
136 unsigned int serial
= htonl(serial_no
);
137 unsigned int serial_length
= sizeof(serial
);
138 uint8_t *serial_non_zero
= (uint8_t*)&serial
;
139 while (!*serial_non_zero
&& serial_length
)
140 { serial_non_zero
++; serial_length
--; }
141 serialno
= CFDataCreate(kCFAllocatorDefault
,
142 serial_non_zero
, serial_length
);
143 require(cert_subject
= test_cert_string_to_subject(subject
), out
);
144 //extensions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
145 //require(extensions, out);
146 //test_cert_key_usage(extensions, key_usage);
148 cert
= SecIdentitySignCertificate(ca_identity
, serialno
,
149 public_key
, cert_subject
, NULL
);
152 CFReleaseSafe(extensions
);
153 CFReleaseSafe(cert_subject
);
154 CFReleaseSafe(serialno
);
160 test_cert_generate_key(uint32_t key_size_in_bits
, CFTypeRef sec_attr_key_type
,
161 SecKeyRef
*private_key
, SecKeyRef
*public_key
)
163 CFNumberRef key_size
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &key_size_in_bits
);
164 const void *keygen_keys
[] = { kSecAttrKeyType
, kSecAttrKeySizeInBits
};
165 const void *keygen_vals
[] = { sec_attr_key_type
, key_size
};
166 CFDictionaryRef parameters
= CFDictionaryCreate(kCFAllocatorDefault
,
167 keygen_keys
, keygen_vals
, array_size(keygen_vals
),
168 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
171 return SecKeyGeneratePair(parameters
, public_key
, private_key
);
174 #endif /* TARGET_OS_IPHONE */