From d7a43d00d7bfe0e3be99bbd38a567c2505b35a09 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Fri, 19 Jan 2018 18:14:11 -0500 Subject: [PATCH] Modify YapDatabase to read converted database, part 2. --- SignalMessaging/utils/OWSDatabaseConverter.m | 41 +++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/SignalMessaging/utils/OWSDatabaseConverter.m b/SignalMessaging/utils/OWSDatabaseConverter.m index c6efffeae..1d039c3ce 100644 --- a/SignalMessaging/utils/OWSDatabaseConverter.m +++ b/SignalMessaging/utils/OWSDatabaseConverter.m @@ -124,14 +124,14 @@ const NSUInteger kSqliteHeaderLength = 32; OWSAssert(headerData.length >= kSQLCipherSaltLength); sqlCipherSaltData = [headerData subdataWithRange:NSMakeRange(0, kSQLCipherSaltLength)]; + DDLogVerbose(@"%@ sqlCipherSaltData: %@", self.logTag, sqlCipherSaltData.hexadecimalString); + // Make sure we successfully persist the salt (persumably in the keychain) before // proceeding with the database conversion or we could leave the app in an // unrecoverable state. saltBlock(sqlCipherSaltData); } - // TODO: Write salt to keychain. - // Hello Matthew, // // I hope you're doing well. We've just pushed some changes out to the SQLCipher prerelease branch on GitHub that @@ -283,6 +283,43 @@ const NSUInteger kSqliteHeaderLength = 32; // BEGIN SQLCipher migration } +#ifdef DEBUG + // We can obtain the database salt in two ways: by reading the first 16 bytes of the encrypted + // header OR by using "PRAGMA cipher_salt". In DEBUG builds, we verify that these two values + // match. + { + sqlite3_stmt *statement; + + char *stmt = "PRAGMA cipher_salt;"; + + status = sqlite3_prepare_v2(db, stmt, (int)strlen(stmt) + 1, &statement, NULL); + if (status != SQLITE_OK) { + DDLogError(@"%@ Error extracting database salt: %d, error: %s", self.logTag, status, sqlite3_errmsg(db)); + return OWSErrorWithCodeDescription( + OWSErrorCodeDatabaseConversionFatalError, @"Error extracting database salt"); + } + + status = sqlite3_step(statement); + if (status != SQLITE_ROW) { + DDLogError(@"%@ Missing database salt: %d, error: %s", self.logTag, status, sqlite3_errmsg(db)); + return OWSErrorWithCodeDescription(OWSErrorCodeDatabaseConversionFatalError, @"Missing database salt"); + } + + const unsigned char *valueBytes = sqlite3_column_text(statement, 0); + int valueLength = sqlite3_column_bytes(statement, 0); + DDLogVerbose(@"%@ value: %d %d", self.logTag, valueLength, valueBytes != NULL); + + NSString *saltString = + [[NSString alloc] initWithBytes:valueBytes length:valueLength encoding:NSUTF8StringEncoding]; + + sqlite3_finalize(statement); + statement = NULL; + + DDLogVerbose(@"%@ saltString: %@", self.logTag, saltString); + + OWSAssert([sqlCipherSaltData.hexadecimalString isEqualToString:saltString]); + } +#endif // ----------------------------------------------------------- //