]> git.saurik.com Git - apple/security.git/blob - sec/Security/SecFramework.c
Security-55163.44.tar.gz
[apple/security.git] / sec / Security / SecFramework.c
1 /*
2 * Copyright (c) 2006-2010 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
24 /*
25 * SecFramework.c - generic non API class specific functions
26 */
27
28 #ifdef STANDALONE
29 /* Allows us to build genanchors against the BaseSDK. */
30 #undef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__
31 #undef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
32 #endif
33
34 #include "SecFramework.h"
35 #include <pthread.h>
36 #include <CoreFoundation/CFBundle.h>
37 #include <CoreFoundation/CFURLAccess.h>
38 #include <Security/SecRandom.h>
39 #include <CommonCrypto/CommonDigest.h>
40 #include <Security/SecAsn1Coder.h>
41 #include <Security/oidsalg.h>
42 #include <fcntl.h>
43 #include <sys/types.h>
44 #include <unistd.h>
45 #include <security_utilities/debugging.h>
46 #include <MacErrors.h>
47 #include <errno.h>
48
49 /* Security.framework's bundle id. */
50 static CFStringRef kSecFrameworkBundleID = CFSTR("com.apple.Security");
51
52 /* Security framework's own bundle used for localized string lookups. */
53 static CFBundleRef kSecFrameworkBundle;
54 static pthread_once_t kSecFrameworkBundleLookup = PTHREAD_ONCE_INIT;
55
56 static void SecFrameworkBundleLookup(void) {
57 kSecFrameworkBundle = CFBundleGetBundleWithIdentifier(kSecFrameworkBundleID);
58 if (kSecFrameworkBundle)
59 CFRetain(kSecFrameworkBundle);
60 }
61
62 CFStringRef SecFrameworkCopyLocalizedString(CFStringRef key,
63 CFStringRef tableName) {
64 pthread_once(&kSecFrameworkBundleLookup, SecFrameworkBundleLookup);
65 if (kSecFrameworkBundle) {
66 return CFBundleCopyLocalizedString(kSecFrameworkBundle, key, key,
67 tableName);
68 }
69
70 CFRetain(key);
71 return key;
72 }
73
74 CFURLRef SecFrameworkCopyResourceURL(CFStringRef resourceName,
75 CFStringRef resourceType, CFStringRef subDirName) {
76 CFURLRef url = NULL;
77 pthread_once(&kSecFrameworkBundleLookup, SecFrameworkBundleLookup);
78 if (kSecFrameworkBundle) {
79 url = CFBundleCopyResourceURL(kSecFrameworkBundle, resourceName,
80 resourceType, subDirName);
81 if (!url) {
82 secwarning("resource: %@.%@ in %@ not found", resourceName,
83 resourceType, subDirName);
84 }
85 }
86
87 return url;
88 }
89
90
91 CFDataRef SecFrameworkCopyResourceContents(CFStringRef resourceName,
92 CFStringRef resourceType, CFStringRef subDirName) {
93 CFURLRef url = SecFrameworkCopyResourceURL(resourceName, resourceType,
94 subDirName);
95 CFDataRef data = NULL;
96 if (url) {
97 SInt32 error;
98 if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,
99 url, &data, NULL, NULL, &error)) {
100 secwarning("read: %@: %d", error);
101 }
102 CFRelease(url);
103 }
104
105 return data;
106 }
107
108 /* Return the SHA1 digest of a chunk of data as newly allocated CFDataRef. */
109 CFDataRef SecSHA1DigestCreate(CFAllocatorRef allocator,
110 const UInt8 *data, CFIndex length) {
111 CFMutableDataRef digest = CFDataCreateMutable(allocator,
112 CC_SHA1_DIGEST_LENGTH);
113 CFDataSetLength(digest, CC_SHA1_DIGEST_LENGTH);
114 //FIXME: Cast from CFIndex to CC_LONG
115 CC_SHA1(data, (CC_LONG)length, CFDataGetMutableBytePtr(digest));
116 return digest;
117 }
118
119 CFDataRef SecDigestCreate(CFAllocatorRef allocator,
120 const SecAsn1Oid *algorithm, const SecAsn1Item *params,
121 const UInt8 *data, CFIndex length) {
122 unsigned char *(*digestFcn)(const void *data, CC_LONG len, unsigned char *md);
123 CFIndex digestLen;
124
125 if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA1)) {
126 digestFcn = CC_SHA1;
127 digestLen = CC_SHA1_DIGEST_LENGTH;
128 } else if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA224)) {
129 digestFcn = CC_SHA224;
130 digestLen = CC_SHA224_DIGEST_LENGTH;
131 } else if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA256)) {
132 digestFcn = CC_SHA256;
133 digestLen = CC_SHA256_DIGEST_LENGTH;
134 } else if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA384)) {
135 digestFcn = CC_SHA384;
136 digestLen = CC_SHA384_DIGEST_LENGTH;
137 } else if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA512)) {
138 digestFcn = CC_SHA512;
139 digestLen = CC_SHA512_DIGEST_LENGTH;
140 } else {
141 return NULL;
142 }
143
144 CFMutableDataRef digest = CFDataCreateMutable(allocator, digestLen);
145 CFDataSetLength(digest, digestLen);
146 //FIXME: Cast from CFIndex to CC_LONG
147 digestFcn(data, (CC_LONG)length, CFDataGetMutableBytePtr(digest));
148 return digest;
149 }
150
151 /* Default random ref for /dev/random. */
152 const SecRandomRef kSecRandomDefault = NULL;
153
154 /* File descriptor for "/dev/random". */
155 static int kSecRandomFD;
156 static pthread_once_t kSecDevRandomOpen = PTHREAD_ONCE_INIT;
157
158 static void SecDevRandomOpen(void) {
159 kSecRandomFD = open("/dev/random", O_RDONLY);
160 }
161
162 int SecRandomCopyBytes(SecRandomRef rnd, size_t count, uint8_t *bytes) {
163 if (rnd != kSecRandomDefault)
164 return paramErr;
165 pthread_once(&kSecDevRandomOpen, SecDevRandomOpen);
166 if (kSecRandomFD < 0)
167 return -1;
168 while (count) {
169 ssize_t bytes_read = read(kSecRandomFD, bytes, count);
170 if (bytes_read == -1) {
171 if (errno == EINTR)
172 continue;
173 return -1;
174 }
175 if (bytes_read == 0) {
176 return -1;
177 }
178 bytes += bytes_read;
179 count -= bytes_read;
180 }
181
182 return 0;
183 }
184
185 #if 0
186 #include <CommonCrypto/CommonDigest.h>
187 #include <stdlib.h>
188
189 /* FIPS rng declarations. */
190 typedef struct __SecRandom *SecRandomRef;
191 SecRandomRef SecRandomCreate(CFIndex randomAlg, CFIndex seedLength,
192 const UInt8 *seed);
193 void SecRandomCopyBytes(SecRandomRef randomref, CFIndex numBytes, UInt8 *outBytes);
194
195 /* FIPS Rng implementation. */
196 struct __SecRandom {
197 CC_SHA1_CTX sha1;
198 CFIndex bytesLeft;
199 UInt8 block[64];
200 };
201
202 SecRandomRef SecRandomCreate(CFIndex randomAlg, CFIndex seedLength,
203 const UInt8 *seed) {
204 SecRandomRef result = (SecRandomRef)malloc(sizeof(struct __SecRandom));
205 CC_SHA1_Init(&result->sha1);
206 memset(result->block + 20, 0, 44);
207 result->bytesLeft = 0;
208
209 if (seedLength) {
210 /* Digest the seed and put it into output. */
211 CC_SHA1(seed, seedLength, result->block);
212 } else {
213 /* Seed 20 bytes from "/dev/srandom". */
214 int fd = open("/dev/srandom", O_RDONLY);
215 if (fd < 0)
216 goto errOut;
217
218 if (read(fd, result->block, 20) != 20)
219 goto errOut;
220
221 close(fd);
222 }
223
224 CC_SHA1_Update(&result->sha1, result->block, 64);
225
226 return result;
227
228 errOut:
229 free(result);
230 return NULL;
231 }
232
233 void SecRandomCopyBytes(SecRandomRef randomref, CFIndex numBytes,
234 UInt8 *outBytes) {
235 while (numBytes > 0) {
236 if (!randomref->bytesLeft) {
237 CC_SHA1_Update(&randomref->sha1, randomref->block, 64);
238 OSWriteBigInt32(randomref->block, 0, randomref->sha1.h0);
239 OSWriteBigInt32(randomref->block, 4, randomref->sha1.h1);
240 OSWriteBigInt32(randomref->block, 8, randomref->sha1.h2);
241 OSWriteBigInt32(randomref->block, 12, randomref->sha1.h3);
242 OSWriteBigInt32(randomref->block, 16, randomref->sha1.h4);
243 randomref->bytesLeft = 20;
244 }
245 CFIndex outLength = (numBytes > randomref->bytesLeft ?
246 randomref->bytesLeft : numBytes);
247 memcpy(outBytes, randomref->block + 20 - randomref->bytesLeft,
248 outLength);
249 randomref->bytesLeft -= outLength;
250 outBytes += outLength;
251 numBytes -= outLength;
252 }
253 }
254 #endif