#ifdef STANDALONE
#undef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__
#undef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
#endif
#include "SecFramework.h"
#include <dispatch/dispatch.h>
#include <CoreFoundation/CFBundle.h>
#include <CoreFoundation/CFURLAccess.h>
#include <Security/SecRandom.h>
#include <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonDigestSPI.h>
#include <Security/SecAsn1Coder.h>
#include <Security/oidsalg.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <utilities/debugging.h>
#include <utilities/SecCFWrappers.h>
#include <Security/SecBase.h>
#include <errno.h>
#include <inttypes.h>
#if !(TARGET_IPHONE_SIMULATOR && defined(IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED) && IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 1090)
#include <sys/guarded.h>
#define USE_GUARDED_OPEN 1
#else
#define USE_GUARDED_OPEN 0
#endif
static CFStringRef kSecFrameworkBundleID = CFSTR("com.apple.Security");
CFGiblisGetSingleton(CFBundleRef, SecFrameworkGetBundle, bundle, ^{
*bundle = CFRetainSafe(CFBundleGetBundleWithIdentifier(kSecFrameworkBundleID));
})
CFStringRef SecFrameworkCopyLocalizedString(CFStringRef key,
CFStringRef tableName) {
CFBundleRef bundle = SecFrameworkGetBundle();
if (bundle)
return CFBundleCopyLocalizedString(bundle, key, key, tableName);
return CFRetainSafe(key);
}
CFURLRef SecFrameworkCopyResourceURL(CFStringRef resourceName,
CFStringRef resourceType, CFStringRef subDirName) {
CFURLRef url = NULL;
CFBundleRef bundle = SecFrameworkGetBundle();
if (bundle) {
url = CFBundleCopyResourceURL(bundle, resourceName,
resourceType, subDirName);
if (!url) {
secwarning("resource: %@.%@ in %@ not found", resourceName,
resourceType, subDirName);
}
}
return url;
}
CFDataRef SecFrameworkCopyResourceContents(CFStringRef resourceName,
CFStringRef resourceType, CFStringRef subDirName) {
CFURLRef url = SecFrameworkCopyResourceURL(resourceName, resourceType,
subDirName);
CFDataRef data = NULL;
if (url) {
SInt32 error;
if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,
url, &data, NULL, NULL, &error)) {
secwarning("read: %ld", (long) error);
}
CFRelease(url);
}
return data;
}
CFDataRef SecSHA1DigestCreate(CFAllocatorRef allocator,
const UInt8 *data, CFIndex length) {
CFMutableDataRef digest = CFDataCreateMutable(allocator,
CC_SHA1_DIGEST_LENGTH);
CFDataSetLength(digest, CC_SHA1_DIGEST_LENGTH);
CCDigest(kCCDigestSHA1, data, (CC_LONG)length, CFDataGetMutableBytePtr(digest));
return digest;
}
CFDataRef SecDigestCreate(CFAllocatorRef allocator,
const SecAsn1Oid *algorithm, const SecAsn1Item *params,
const UInt8 *data, CFIndex length) {
unsigned char *(*digestFcn)(const void *data, CC_LONG len, unsigned char *md);
CFIndex digestLen;
if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA1)) {
digestFcn = CC_SHA1;
digestLen = CC_SHA1_DIGEST_LENGTH;
} else if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA224)) {
digestFcn = CC_SHA224;
digestLen = CC_SHA224_DIGEST_LENGTH;
} else if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA256)) {
digestFcn = CC_SHA256;
digestLen = CC_SHA256_DIGEST_LENGTH;
} else if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA384)) {
digestFcn = CC_SHA384;
digestLen = CC_SHA384_DIGEST_LENGTH;
} else if (SecAsn1OidCompare(algorithm, &CSSMOID_SHA512)) {
digestFcn = CC_SHA512;
digestLen = CC_SHA512_DIGEST_LENGTH;
} else {
return NULL;
}
CFMutableDataRef digest = CFDataCreateMutable(allocator, digestLen);
CFDataSetLength(digest, digestLen);
digestFcn(data, (CC_LONG)length, CFDataGetMutableBytePtr(digest));
return digest;
}
#include <CommonCrypto/CommonRandomSPI.h>
const SecRandomRef kSecRandomDefault = NULL;
int SecRandomCopyBytes(SecRandomRef rnd, size_t count, uint8_t *bytes) {
if (rnd != kSecRandomDefault)
return errSecParam;
return CCRandomCopyBytes(kCCRandomDefault, bytes, count);
}
#if 0
#include <CommonCrypto/CommonDigest.h>
#include <stdlib.h>
typedef struct __SecRandom *SecRandomRef;
SecRandomRef SecRandomCreate(CFIndex randomAlg, CFIndex seedLength,
const UInt8 *seed);
void SecRandomCopyBytes(SecRandomRef randomref, CFIndex numBytes, UInt8 *outBytes);
struct __SecRandom {
CC_SHA1_CTX sha1;
CFIndex bytesLeft;
UInt8 block[64];
};
SecRandomRef SecRandomCreate(CFIndex randomAlg, CFIndex seedLength,
const UInt8 *seed) {
SecRandomRef result = (SecRandomRef)malloc(sizeof(struct __SecRandom));
CC_SHA1_Init(&result->sha1);
memset(result->block + 20, 0, 44);
result->bytesLeft = 0;
if (seedLength) {
CCDigest(kCCDigestSHA1, seed, seedLength, result->block);
} else {
int fd = open("/dev/srandom", O_RDONLY);
if (fd < 0)
goto errOut;
if (read(fd, result->block, 20) != 20)
goto errOut;
close(fd);
}
CC_SHA1_Update(&result->sha1, result->block, 64);
return result;
errOut:
free(result);
return NULL;
}
void SecRandomCopyBytes(SecRandomRef randomref, CFIndex numBytes,
UInt8 *outBytes) {
while (numBytes > 0) {
if (!randomref->bytesLeft) {
CC_SHA1_Update(&randomref->sha1, randomref->block, 64);
OSWriteBigInt32(randomref->block, 0, randomref->sha1.h0);
OSWriteBigInt32(randomref->block, 4, randomref->sha1.h1);
OSWriteBigInt32(randomref->block, 8, randomref->sha1.h2);
OSWriteBigInt32(randomref->block, 12, randomref->sha1.h3);
OSWriteBigInt32(randomref->block, 16, randomref->sha1.h4);
randomref->bytesLeft = 20;
}
CFIndex outLength = (numBytes > randomref->bytesLeft ?
randomref->bytesLeft : numBytes);
memcpy(outBytes, randomref->block + 20 - randomref->bytesLeft,
outLength);
randomref->bytesLeft -= outLength;
outBytes += outLength;
numBytes -= outLength;
}
}
#endif