2 * Copyright (c) 2006-2010,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@
25 * SecFramework.c - generic non API class specific functions
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__
34 #include "SecFramework.h"
35 #include <dispatch/dispatch.h>
36 #include <CoreFoundation/CFBundle.h>
37 #include <CoreFoundation/CFURLAccess.h>
38 #include <Security/SecRandom.h>
39 #include <CommonCrypto/CommonDigest.h>
40 #include <CommonCrypto/CommonDigestSPI.h>
41 #include <Security/SecAsn1Coder.h>
42 #include <Security/oidsalg.h>
44 #include <sys/types.h>
46 #include <utilities/debugging.h>
47 #include <utilities/SecCFWrappers.h>
48 #include <Security/SecBase.h>
52 #if !(TARGET_IPHONE_SIMULATOR && defined(IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED) && IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 1090)
53 #include <sys/guarded.h>
54 #define USE_GUARDED_OPEN 1
56 #define USE_GUARDED_OPEN 0
60 /* Security.framework's bundle id. */
61 static CFStringRef kSecFrameworkBundleID
= CFSTR("com.apple.Security");
63 CFGiblisGetSingleton(CFBundleRef
, SecFrameworkGetBundle
, bundle
, ^{
64 *bundle
= CFRetainSafe(CFBundleGetBundleWithIdentifier(kSecFrameworkBundleID
));
67 CFStringRef
SecFrameworkCopyLocalizedString(CFStringRef key
,
68 CFStringRef tableName
) {
69 CFBundleRef bundle
= SecFrameworkGetBundle();
71 return CFBundleCopyLocalizedString(bundle
, key
, key
, tableName
);
73 return CFRetainSafe(key
);
76 CFURLRef
SecFrameworkCopyResourceURL(CFStringRef resourceName
,
77 CFStringRef resourceType
, CFStringRef subDirName
) {
79 CFBundleRef bundle
= SecFrameworkGetBundle();
81 url
= CFBundleCopyResourceURL(bundle
, resourceName
,
82 resourceType
, subDirName
);
84 secwarning("resource: %@.%@ in %@ not found", resourceName
,
85 resourceType
, subDirName
);
92 CFDataRef
SecFrameworkCopyResourceContents(CFStringRef resourceName
,
93 CFStringRef resourceType
, CFStringRef subDirName
) {
94 CFURLRef url
= SecFrameworkCopyResourceURL(resourceName
, resourceType
,
96 CFDataRef data
= NULL
;
99 if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault
,
100 url
, &data
, NULL
, NULL
, &error
)) {
101 secwarning("read: %ld", (long) error
);
109 /* Return the SHA1 digest of a chunk of data as newly allocated CFDataRef. */
110 CFDataRef
SecSHA1DigestCreate(CFAllocatorRef allocator
,
111 const UInt8
*data
, CFIndex length
) {
112 CFMutableDataRef digest
= CFDataCreateMutable(allocator
,
113 CC_SHA1_DIGEST_LENGTH
);
114 CFDataSetLength(digest
, CC_SHA1_DIGEST_LENGTH
);
115 CCDigest(kCCDigestSHA1
, data
, length
, CFDataGetMutableBytePtr(digest
));
119 CFDataRef
SecSHA256DigestCreate(CFAllocatorRef allocator
,
120 const UInt8
*data
, CFIndex length
) {
121 CFMutableDataRef digest
= CFDataCreateMutable(allocator
,
122 CC_SHA256_DIGEST_LENGTH
);
123 CFDataSetLength(digest
, CC_SHA256_DIGEST_LENGTH
);
124 CCDigest(kCCDigestSHA256
, data
, length
, CFDataGetMutableBytePtr(digest
));
128 CFDataRef
SecSHA256DigestCreateFromData(CFAllocatorRef allocator
, CFDataRef data
) {
129 CFMutableDataRef digest
= CFDataCreateMutable(allocator
,
130 CC_SHA256_DIGEST_LENGTH
);
131 CFDataSetLength(digest
, CC_SHA256_DIGEST_LENGTH
);
132 CCDigest(kCCDigestSHA256
, CFDataGetBytePtr(data
), CFDataGetLength(data
), CFDataGetMutableBytePtr(digest
));
136 CFDataRef
SecDigestCreate(CFAllocatorRef allocator
,
137 const SecAsn1Oid
*algorithm
, const SecAsn1Item
*params
,
138 const UInt8
*data
, CFIndex length
) {
139 unsigned char *(*digestFcn
)(const void *data
, CC_LONG len
, unsigned char *md
);
142 if (SecAsn1OidCompare(algorithm
, &CSSMOID_SHA1
)) {
144 digestLen
= CC_SHA1_DIGEST_LENGTH
;
145 } else if (SecAsn1OidCompare(algorithm
, &CSSMOID_SHA224
)) {
146 digestFcn
= CC_SHA224
;
147 digestLen
= CC_SHA224_DIGEST_LENGTH
;
148 } else if (SecAsn1OidCompare(algorithm
, &CSSMOID_SHA256
)) {
149 digestFcn
= CC_SHA256
;
150 digestLen
= CC_SHA256_DIGEST_LENGTH
;
151 } else if (SecAsn1OidCompare(algorithm
, &CSSMOID_SHA384
)) {
152 digestFcn
= CC_SHA384
;
153 digestLen
= CC_SHA384_DIGEST_LENGTH
;
154 } else if (SecAsn1OidCompare(algorithm
, &CSSMOID_SHA512
)) {
155 digestFcn
= CC_SHA512
;
156 digestLen
= CC_SHA512_DIGEST_LENGTH
;
161 CFMutableDataRef digest
= CFDataCreateMutable(allocator
, digestLen
);
162 CFDataSetLength(digest
, digestLen
);
163 //FIXME: Cast from CFIndex to CC_LONG
164 digestFcn(data
, (CC_LONG
)length
, CFDataGetMutableBytePtr(digest
));
169 #include <CommonCrypto/CommonRandomSPI.h>
170 const SecRandomRef kSecRandomDefault
= NULL
;
172 int SecRandomCopyBytes(SecRandomRef rnd
, size_t count
, uint8_t *bytes
) {
173 if (rnd
!= kSecRandomDefault
)
175 return CCRandomCopyBytes(kCCRandomDefault
, bytes
, count
);
179 #include <CommonCrypto/CommonDigest.h>
182 /* FIPS rng declarations. */
183 typedef struct __SecRandom
*SecRandomRef
;
184 SecRandomRef
SecRandomCreate(CFIndex randomAlg
, CFIndex seedLength
,
186 void SecRandomCopyBytes(SecRandomRef randomref
, CFIndex numBytes
, UInt8
*outBytes
);
188 /* FIPS Rng implementation. */
195 SecRandomRef
SecRandomCreate(CFIndex randomAlg
, CFIndex seedLength
,
197 SecRandomRef result
= (SecRandomRef
)malloc(sizeof(struct __SecRandom
));
198 CC_SHA1_Init(&result
->sha1
);
199 memset(result
->block
+ 20, 0, 44);
200 result
->bytesLeft
= 0;
203 /* Digest the seed and put it into output. */
204 CCDigest(kCCDigestSHA1
, seed
, seedLength
, result
->block
);
206 /* Seed 20 bytes from "/dev/srandom". */
207 int fd
= open("/dev/srandom", O_RDONLY
);
211 if (read(fd
, result
->block
, 20) != 20)
217 CC_SHA1_Update(&result
->sha1
, result
->block
, 64);
226 void SecRandomCopyBytes(SecRandomRef randomref
, CFIndex numBytes
,
228 while (numBytes
> 0) {
229 if (!randomref
->bytesLeft
) {
230 CC_SHA1_Update(&randomref
->sha1
, randomref
->block
, 64);
231 OSWriteBigInt32(randomref
->block
, 0, randomref
->sha1
.h0
);
232 OSWriteBigInt32(randomref
->block
, 4, randomref
->sha1
.h1
);
233 OSWriteBigInt32(randomref
->block
, 8, randomref
->sha1
.h2
);
234 OSWriteBigInt32(randomref
->block
, 12, randomref
->sha1
.h3
);
235 OSWriteBigInt32(randomref
->block
, 16, randomref
->sha1
.h4
);
236 randomref
->bytesLeft
= 20;
238 CFIndex outLength
= (numBytes
> randomref
->bytesLeft
?
239 randomref
->bytesLeft
: numBytes
);
240 memcpy(outBytes
, randomref
->block
+ 20 - randomref
->bytesLeft
,
242 randomref
->bytesLeft
-= outLength
;
243 outBytes
+= outLength
;
244 numBytes
-= outLength
;