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