1/* 2 * Copyright (c) 2009,2012-2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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 11 * file. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 * 23 * testcert.c 24 */ 25 26#include <TargetConditionals.h> 27 28#if TARGET_OS_IPHONE 29 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> 36 37#include <AssertMacros.h> 38 39#include "testcert.h" 40 41static inline CF_RETURNS_RETAINED CFMutableArrayRef maa(CFMutableArrayRef array CF_CONSUMED, CFTypeRef a CF_CONSUMED) { 42 CFMutableArrayRef ma = array; 43 if (!ma) 44 ma = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 45 if (ma) { 46 CFArrayAppendValue(ma, a); 47 } 48 CFRelease(a); 49 return ma; 50} 51 52 53CF_RETURNS_RETAINED 54CFArrayRef test_cert_string_to_subject(CFStringRef subject) 55{ 56 CFMutableArrayRef subject_array = NULL; 57 char buffer[1024]; 58 59 if (!CFStringGetCString(subject, buffer, sizeof(buffer), kCFStringEncodingASCII)) 60 goto out; 61 62 char *s = buffer, *e = NULL; 63 while ( (e = strchr(s, ',')) || (e = strchr(s, '\0')) ) { 64 if (s == e) 65 break; 66 if (*e && (*(e-1) == '\\')) 67 continue; 68 char *k; 69 while ((k = strchr(s, '=')) && 70 (*(k-1) == '\\')); 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))); 75 } 76 if (*e == '\0') 77 break; 78 s = e + 1; 79 } 80 81out: 82 return subject_array; 83} 84 85 86static void test_cert_key_usage(CFMutableDictionaryRef extensions_dict, unsigned int key_usage) 87{ 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); 92} 93 94 95static void test_cert_path_length(CFMutableDictionaryRef extensions_dict, unsigned int path_length) 96{ 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); 101} 102 103 104SecIdentityRef test_cert_create_root_certificate(CFStringRef subject, SecKeyRef public_key, SecKeyRef private_key) 105{ 106 SecCertificateRef ca_cert = NULL; 107 SecIdentityRef ca_identity = NULL; 108 CFMutableDictionaryRef extensions = NULL; 109 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); 118 119out: 120 CFReleaseSafe(extensions); 121 CFReleaseSafe(ca_subject); 122 CFReleaseSafe(ca_cert); 123 124 return ca_identity; 125} 126 127SecCertificateRef test_cert_issue_certificate(SecIdentityRef ca_identity, 128 SecKeyRef public_key, CFStringRef subject, 129 unsigned int serial_no, unsigned int key_usage) 130{ 131 SecCertificateRef cert = NULL; 132 CFArrayRef cert_subject = NULL; 133 CFDataRef serialno = NULL; 134 CFMutableDictionaryRef extensions = NULL; 135 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); 147 148 cert = SecIdentitySignCertificate(ca_identity, serialno, 149 public_key, cert_subject, NULL); 150 151out: 152 CFReleaseSafe(extensions); 153 CFReleaseSafe(cert_subject); 154 CFReleaseSafe(serialno); 155 156 return cert; 157} 158 159OSStatus 160test_cert_generate_key(uint32_t key_size_in_bits, CFTypeRef sec_attr_key_type, 161 SecKeyRef *private_key, SecKeyRef *public_key) 162{ 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); 169 CFRelease(key_size); 170 171 return SecKeyGeneratePair(parameters, public_key, private_key); 172} 173 174#endif /* TARGET_OS_IPHONE */ 175