]> git.saurik.com Git - apple/security.git/blob - libsecurity_keychain/lib/SecFrameworkP.c
Security-55471.tar.gz
[apple/security.git] / libsecurity_keychain / lib / SecFrameworkP.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
29 #include "SecFrameworkP.h"
30 #include <pthread.h>
31 #include <CoreFoundation/CFBundle.h>
32 #include <CoreFoundation/CFURLAccess.h>
33 #if 0
34 #include "SecRandomP.h"
35 #endif
36 #include <CommonCrypto/CommonDigest.h>
37 #include <Security/SecAsn1Coder.h>
38 #include <Security/oidsalg.h>
39 #include <fcntl.h>
40 #include <sys/types.h>
41 #include <unistd.h>
42 #include <errno.h>
43 #include <dlfcn.h>
44 #include <string.h>
45 #include <CoreFoundation/CFBundlePriv.h>
46
47 #include <utilities/debugging.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 #if 0
57 // copied from SecAsn1Coder.c
58
59 bool SecAsn1OidCompare(const SecAsn1Oid *oid1, const SecAsn1Oid *oid2) {
60 if (!oid1 || !oid2)
61 return oid1 == oid2;
62 if (oid1->Length != oid2->Length)
63 return false;
64 return !memcmp(oid1->Data, oid2->Data, oid1->Length);
65 }
66 #endif
67
68 static void SecFrameworkBundleLookup(void) {
69 // figure out the path to our executable
70 Dl_info info;
71 dladdr("", &info);
72
73 // make a file URL from the returned string
74 CFURLRef urlRef = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8*) info.dli_fname, strlen(info.dli_fname), false);
75 kSecFrameworkBundle = _CFBundleCreateWithExecutableURLIfLooksLikeBundle(NULL, urlRef);
76 CFRelease(urlRef);
77
78 if (kSecFrameworkBundle)
79 CFRetain(kSecFrameworkBundle);
80 }
81
82 CFStringRef SecFrameworkCopyLocalizedString(CFStringRef key,
83 CFStringRef tableName) {
84 pthread_once(&kSecFrameworkBundleLookup, SecFrameworkBundleLookup);
85 if (kSecFrameworkBundle) {
86 return CFBundleCopyLocalizedString(kSecFrameworkBundle, key, key,
87 tableName);
88 }
89
90 CFRetain(key);
91 return key;
92 }
93
94 CFURLRef SecFrameworkCopyResourceURL(CFStringRef resourceName,
95 CFStringRef resourceType, CFStringRef subDirName) {
96 CFURLRef url = NULL;
97 pthread_once(&kSecFrameworkBundleLookup, SecFrameworkBundleLookup);
98 if (kSecFrameworkBundle) {
99 url = CFBundleCopyResourceURL(kSecFrameworkBundle, resourceName,
100 resourceType, subDirName);
101 if (!url) {
102 secdebug("SecFramework", "resource: %@.%@ in %@ not found", resourceName,
103 resourceType, subDirName);
104 }
105 }
106
107 return url;
108 }
109
110
111 CFDataRef SecFrameworkCopyResourceContents(CFStringRef resourceName,
112 CFStringRef resourceType, CFStringRef subDirName) {
113 CFURLRef url = SecFrameworkCopyResourceURL(resourceName, resourceType,
114 subDirName);
115 CFDataRef data = NULL;
116 if (url) {
117 SInt32 error;
118 if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,
119 url, &data, NULL, NULL, &error)) {
120 secdebug("SecFramework", "read: %d", (int)error);
121 }
122 CFRelease(url);
123 }
124
125 return data;
126 }
127
128 /* Return the SHA1 digest of a chunk of data as newly allocated CFDataRef. */
129 CFDataRef SecSHA1DigestCreate(CFAllocatorRef allocator,
130 const UInt8 *data, CFIndex length) {
131 CFMutableDataRef digest = CFDataCreateMutable(allocator,
132 CC_SHA1_DIGEST_LENGTH);
133 CFDataSetLength(digest, CC_SHA1_DIGEST_LENGTH);
134 CC_SHA1(data, (CC_LONG)length, CFDataGetMutableBytePtr(digest));
135 return digest;
136 }
137
138 #if 0
139 CFDataRef SecDigestCreate(CFAllocatorRef allocator,
140 const SecAsn1Oid *algorithm, const SecAsn1Item *params,
141 const UInt8 *data, CFIndex length) {
142 unsigned char *(*digestFcn)(const void *data, CC_LONG len, unsigned char *md);
143 CFIndex digestLen;
144
145 if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA1)) {
146 digestFcn = CC_SHA1;
147 digestLen = CC_SHA1_DIGEST_LENGTH;
148 } else if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA224)) {
149 digestFcn = CC_SHA224;
150 digestLen = CC_SHA224_DIGEST_LENGTH;
151 } else if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA256)) {
152 digestFcn = CC_SHA256;
153 digestLen = CC_SHA256_DIGEST_LENGTH;
154 } else if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA384)) {
155 digestFcn = CC_SHA384;
156 digestLen = CC_SHA384_DIGEST_LENGTH;
157 } else if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA512)) {
158 digestFcn = CC_SHA512;
159 digestLen = CC_SHA512_DIGEST_LENGTH;
160 } else {
161 return NULL;
162 }
163
164 CFMutableDataRef digest = CFDataCreateMutable(allocator, digestLen);
165 CFDataSetLength(digest, digestLen);
166 digestFcn(data, length, CFDataGetMutableBytePtr(digest));
167 return digest;
168 }
169 #endif
170
171 #if 0
172
173 /* Default random ref for /dev/random. */
174 const SecRandomRef kSecRandomDefault = NULL;
175
176 /* File descriptor for "/dev/random". */
177 static int kSecRandomFD;
178 static pthread_once_t kSecDevRandomOpen = PTHREAD_ONCE_INIT;
179
180 static void SecDevRandomOpen(void) {
181 kSecRandomFD = open("/dev/random", O_RDONLY);
182 }
183
184 int SecRandomCopyBytes(SecRandomRef rnd, size_t count, uint8_t *bytes) {
185 if (rnd != kSecRandomDefault)
186 return errSecParam;
187 pthread_once(&kSecDevRandomOpen, SecDevRandomOpen);
188 if (kSecRandomFD < 0)
189 return -1;
190 while (count) {
191 ssize_t bytes_read = read(kSecRandomFD, bytes, count);
192 if (bytes_read == -1) {
193 if (errno == EINTR)
194 continue;
195 return -1;
196 }
197 if (bytes_read == 0) {
198 return -1;
199 }
200 count -= bytes_read;
201 }
202
203 return 0;
204 }
205
206 #include <CommonCrypto/CommonDigest.h>
207 #include <stdlib.h>
208
209 /* FIPS rng declarations. */
210 typedef struct __SecRandom *SecRandomRef;
211 SecRandomRef SecRandomCreate(CFIndex randomAlg, CFIndex seedLength,
212 const UInt8 *seed);
213 void SecRandomCopyBytes(SecRandomRef randomref, CFIndex numBytes, UInt8 *outBytes);
214
215 /* FIPS Rng implementation. */
216 struct __SecRandom {
217 CC_SHA1_CTX sha1;
218 CFIndex bytesLeft;
219 UInt8 block[64];
220 };
221
222 SecRandomRef SecRandomCreate(CFIndex randomAlg, CFIndex seedLength,
223 const UInt8 *seed) {
224 SecRandomRef result = (SecRandomRef)malloc(sizeof(struct __SecRandom));
225 CC_SHA1_Init(&result->sha1);
226 memset(result->block + 20, 0, 44);
227 result->bytesLeft = 0;
228
229 if (seedLength) {
230 /* Digest the seed and put it into output. */
231 CC_SHA1(seed, seedLength, result->block);
232 } else {
233 /* Seed 20 bytes from "/dev/srandom". */
234 int fd = open("/dev/srandom", O_RDONLY);
235 if (fd < 0)
236 goto errOut;
237
238 if (read(fd, result->block, 20) != 20)
239 goto errOut;
240
241 close(fd);
242 }
243
244 CC_SHA1_Update(&result->sha1, result->block, 64);
245
246 return result;
247
248 errOut:
249 free(result);
250 return NULL;
251 }
252
253 void SecRandomCopyBytes(SecRandomRef randomref, CFIndex numBytes,
254 UInt8 *outBytes) {
255 while (numBytes > 0) {
256 if (!randomref->bytesLeft) {
257 CC_SHA1_Update(&randomref->sha1, randomref->block, 64);
258 OSWriteBigInt32(randomref->block, 0, randomref->sha1.h0);
259 OSWriteBigInt32(randomref->block, 4, randomref->sha1.h1);
260 OSWriteBigInt32(randomref->block, 8, randomref->sha1.h2);
261 OSWriteBigInt32(randomref->block, 12, randomref->sha1.h3);
262 OSWriteBigInt32(randomref->block, 16, randomref->sha1.h4);
263 randomref->bytesLeft = 20;
264 }
265 CFIndex outLength = (numBytes > randomref->bytesLeft ?
266 randomref->bytesLeft : numBytes);
267 memcpy(outBytes, randomref->block + 20 - randomref->bytesLeft,
268 outLength);
269 randomref->bytesLeft -= outLength;
270 outBytes += outLength;
271 numBytes -= outLength;
272 }
273 }
274 #endif