X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/6b200bc335dc93c5516ccb52f14bd896d8c7fad7..07691282a056c4efea71e1e505527601e8cc166b:/OSX/libsecurity_keychain/lib/SecRecoveryPassword.c diff --git a/OSX/libsecurity_keychain/lib/SecRecoveryPassword.c b/OSX/libsecurity_keychain/lib/SecRecoveryPassword.c index 55a59146..a409f0fd 100644 --- a/OSX/libsecurity_keychain/lib/SecRecoveryPassword.c +++ b/OSX/libsecurity_keychain/lib/SecRecoveryPassword.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ #include #include #include +#include CFStringRef kSecRecVersionNumber = CFSTR("SRVersionNumber"); CFStringRef kSecRecQuestions = CFSTR("SRQuestions"); @@ -88,19 +90,17 @@ sec_debug_imp(int level, const char *funcname, char *format, ...) { // Read /dev/random for random bytes static CFDataRef -getRandomBytes(size_t len) +createRandomBytes(size_t len) { - uint8_t *buffer; - CFDataRef randData = NULL; - int fdrand; - - if((buffer = malloc(len)) == NULL) return NULL; - if((fdrand = open("/dev/random", O_RDONLY)) == -1) return NULL; - if(read(fdrand, buffer, len) == len) randData = CFDataCreate(kCFAllocatorDefault, (const UInt8 *) buffer, len); - close(fdrand); - - free(buffer); - return randData; + CFMutableDataRef data = CFDataCreateMutable(NULL, len); + if (data == NULL) + return NULL; + CFDataSetLength(data, len); + if (SecRandomCopyBytes(kSecRandomDefault, len, CFDataGetMutableBytePtr(data)) != noErr) { + CFRelease(data); + return NULL; + } + return data; } // This is the normalization routine - subject to change. We need to make sure that whitespace is removed and @@ -131,7 +131,8 @@ static void secNormalize(CFMutableStringRef theString, CFLocaleRef theLocale) #define MAXANSWERBUFF 4096 #define PBKDF_ROUNDS 100000 -static SecKeyRef secDeriveKeyFromAnswers(CFArrayRef answers, CFLocaleRef theLocale) +static SecKeyRef CF_RETURNS_RETAINED +secDeriveKeyFromAnswers(CFArrayRef answers, CFLocaleRef theLocale) { static const uint8_t salt[16] = { 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x1F }; static const int saltLen = sizeof(salt); @@ -209,7 +210,7 @@ static SecKeyRef secDeriveKeyFromAnswers(CFArrayRef answers, CFLocaleRef theLoca // Single shot CFString processing routines for digests/encoding/encrypt/decrypt static CFDataRef -digestString(CFStringRef str) +createDigestString(CFStringRef str) { CFDataRef retval = NULL; CFErrorRef error = NULL; @@ -222,12 +223,14 @@ digestString(CFStringRef str) if(error == NULL) { retval = SecTransformExecute(digestTrans, &error); if(retval == NULL) { - secDebug(ASL_LEVEL_ERR, "Couldn't create digest %s\n", CFStringGetCStringPtr(CFErrorCopyFailureReason(error), kCFStringEncodingUTF8)); + CFStringRef errorReason = CFErrorCopyFailureReason(error); + secDebug(ASL_LEVEL_ERR, "Couldn't create digest %s\n", CFStringGetCStringPtr(errorReason, kCFStringEncodingUTF8)); + CFReleaseNull(errorReason); } } - CFRelease(digestTrans); } - CFRelease(inputString); + CFReleaseNull(digestTrans); + CFReleaseNull(inputString); return retval; } @@ -255,29 +258,47 @@ b64decode(CFDataRef input) return retval; } -static CFDataRef +static CFDataRef CF_RETURNS_RETAINED encryptString(SecKeyRef wrapKey, CFDataRef iv, CFStringRef str) { CFDataRef retval = NULL; CFErrorRef error = NULL; CFDataRef inputString = CFStringCreateExternalRepresentation(kCFAllocatorDefault, str, kCFStringEncodingMacRoman, 0xff); - - SecTransformRef encryptTrans = SecEncryptTransformCreate(wrapKey, &error); - if(error == NULL) { - SecTransformRef group = SecTransformCreateGroupTransform(); - - SecTransformSetAttribute(encryptTrans, kSecEncryptionMode, kSecModeCBCKey, &error); - if(error == NULL) SecTransformSetAttribute(encryptTrans, kSecPaddingKey, kSecPaddingPKCS7Key, &error); - if(error == NULL) SecTransformSetAttribute(encryptTrans, kSecTransformInputAttributeName, inputString, &error); - if(error == NULL) SecTransformSetAttribute(encryptTrans, kSecIVKey, iv, &error); - SecTransformRef encodeTrans = SecEncodeTransformCreate(kSecBase64Encoding, &error); - SecTransformConnectTransforms(encryptTrans, kSecTransformOutputAttributeName, encodeTrans, kSecTransformInputAttributeName, group, &error); - CFRelease(encodeTrans); - CFRelease(encryptTrans); - if(error == NULL) retval = SecTransformExecute(group, &error); - if(error != NULL) secDebug(ASL_LEVEL_ERR, "Failed to encrypt recovery password\n", NULL); - CFRelease(group); + SecTransformRef encrypt = NULL; + SecTransformRef encode = NULL; + SecTransformRef group = NULL; + + encrypt = SecEncryptTransformCreate(wrapKey, &error); + if (error) goto out; + SecTransformSetAttribute(encrypt, kSecEncryptionMode, kSecModeCBCKey, &error); + if (error) goto out; + SecTransformSetAttribute(encrypt, kSecPaddingKey, kSecPaddingPKCS7Key, &error); + if (error) goto out; + SecTransformSetAttribute(encrypt, kSecTransformInputAttributeName, inputString, &error); + if (error) goto out; + SecTransformSetAttribute(encrypt, kSecIVKey, iv, &error); + if (error) goto out; + + encode = SecEncodeTransformCreate(kSecBase64Encoding, &error); + if (error) goto out; + + group = SecTransformCreateGroupTransform(); + SecTransformConnectTransforms(encrypt, kSecTransformOutputAttributeName, encode, kSecTransformInputAttributeName, group, &error); + if (error) goto out; + retval = SecTransformExecute(group, &error); + if (error) goto out; + +out: + if (error) { + secerror("Failed to encrypt recovery password: %@", error); } + + CFReleaseNull(error); + CFReleaseNull(inputString); + CFReleaseNull(encrypt); + CFReleaseNull(encode); + CFReleaseNull(group); + return retval; } @@ -287,28 +308,43 @@ decryptString(SecKeyRef wrapKey, CFDataRef iv, CFDataRef wrappedPassword) { CFStringRef retval = NULL; CFDataRef retData = NULL; - CFErrorRef error = NULL; - - SecTransformRef decryptTrans = SecDecryptTransformCreate(wrapKey, &error); - if(error == NULL) { - SecTransformRef group = SecTransformCreateGroupTransform(); - - SecTransformRef decodeTrans = SecDecodeTransformCreate(kSecBase64Encoding, &error); - if(error == NULL) SecTransformSetAttribute(decodeTrans, kSecTransformInputAttributeName, wrappedPassword, &error); - - if(error == NULL) SecTransformSetAttribute(decryptTrans, kSecEncryptionMode, kSecModeCBCKey, &error); - if(error == NULL) SecTransformSetAttribute(decryptTrans, kSecPaddingKey, kSecPaddingPKCS7Key, &error); - if(error == NULL) SecTransformSetAttribute(decryptTrans, kSecIVKey, iv, &error); - SecTransformConnectTransforms(decodeTrans, kSecTransformOutputAttributeName, decryptTrans, kSecTransformInputAttributeName, group, &error); - CFRelease(decodeTrans); - CFRelease(decryptTrans); - if(error == NULL) retData = SecTransformExecute(group, &error); - - if(error == NULL) retval = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, retData, kCFStringEncodingMacRoman); - else secDebug(ASL_LEVEL_ERR, "Failed to decrypt recovery password\n", NULL); - CFRelease(group); + CFErrorRef error = NULL; + SecTransformRef decode = NULL; + SecTransformRef decrypt = NULL; + SecTransformRef group = NULL; + + decode = SecDecodeTransformCreate(kSecBase64Encoding, &error); + if (error) goto out; + SecTransformSetAttribute(decode, kSecTransformInputAttributeName, wrappedPassword, &error); + if (error) goto out; + + decrypt = SecDecryptTransformCreate(wrapKey, &error); + if (error) goto out; + SecTransformSetAttribute(decrypt, kSecEncryptionMode, kSecModeCBCKey, &error); + if (error) goto out; + SecTransformSetAttribute(decrypt, kSecPaddingKey, kSecPaddingPKCS7Key, &error); + if (error) goto out; + SecTransformSetAttribute(decrypt, kSecIVKey, iv, &error); + if (error) goto out; + + group = SecTransformCreateGroupTransform(); + SecTransformConnectTransforms(decode, kSecTransformOutputAttributeName, decrypt, kSecTransformInputAttributeName, group, &error); + if (error) goto out; + retData = SecTransformExecute(group, &error); + if (error) goto out; + retval = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, retData, kCFStringEncodingMacRoman); + +out: + if (error) { + secerror("Failed to decrypt recovery password: %@", error); } - CFReleaseNull(decryptTrans); + + CFReleaseNull(retData); + CFReleaseNull(error); + CFReleaseNull(decode); + CFReleaseNull(decrypt); + CFReleaseNull(group); + return retval; } @@ -320,7 +356,7 @@ createIVFromPassword(CFStringRef password) { CFDataRef hashedPassword, retval; CFMutableDataRef iv; - if((hashedPassword = digestString(password)) == NULL) return NULL; + if((hashedPassword = createDigestString(password)) == NULL) return NULL; iv = CFDataCreateMutableCopy(kCFAllocatorDefault, CFDataGetLength(hashedPassword)+1, hashedPassword); CFDataDeleteBytes(iv, CFRangeMake(IVBYTECOUNT, CFDataGetLength(iv)-IVBYTECOUNT)); retval = CFDataCreateCopy(kCFAllocatorDefault, iv); @@ -341,54 +377,66 @@ createIVFromPassword(CFStringRef password) * recovery dictionary. */ -CFDictionaryRef +CFDictionaryRef CF_RETURNS_RETAINED SecWrapRecoveryPasswordWithAnswers(CFStringRef password, CFArrayRef questions, CFArrayRef answers) { uint32_t vers = 1; - CFDataRef iv; - CFDataRef wrappedPassword; + CFDataRef iv = NULL; + CFDataRef wrappedPassword = NULL; CFMutableDictionaryRef retval = NULL; CFLocaleRef theLocale = CFLocaleCopyCurrent(); CFStringRef theLocaleString = CFLocaleGetIdentifier(theLocale); + SecKeyRef wrapKey = NULL; CFIndex ix, limit; - if (!password || !questions || !answers) - return NULL; + if (!password || !questions || !answers) { + goto error; + } limit = CFArrayGetCount(answers); - if (limit != CFArrayGetCount(questions)) - return NULL; // Error + if (limit != CFArrayGetCount(questions)) { + goto error; + } CFTypeRef chkval; for (ix=0; ix