]> git.saurik.com Git - apple/security.git/blobdiff - securityd/src/dbcrypto.cpp
Security-59306.101.1.tar.gz
[apple/security.git] / securityd / src / dbcrypto.cpp
index b009f0036c55c46d9b930626d500960b2c308629..4fed2f52d2d89c45750d124ae5ea6e55c3f31a25 100644 (file)
@@ -26,6 +26,8 @@
 // dbcrypto - cryptographic core for database and key blob cryptography
 //
 #include "dbcrypto.h"
+#include "SecRandom.h"
+#include <security_utilities/casts.h>
 #include <securityd_client/ssblob.h>
 #include "server.h"            // just for Server::csp()
 #include <security_cdsa_client/genkey.h>
@@ -43,9 +45,14 @@ using LowLevelMemoryUtilities::fieldOffsetOf;
 // The CryptoCore constructor doesn't do anything interesting.
 // It just initializes us to "empty".
 //
-DatabaseCryptoCore::DatabaseCryptoCore() : mBlobVersion(CommonBlob::version_MacOS_10_0), mHaveMaster(false), mIsValid(false)
+DatabaseCryptoCore::DatabaseCryptoCore(uint32 requestedVersion) : mBlobVersion(CommonBlob::version_MacOS_10_0), mHaveMaster(false), mIsValid(false)
 {
-    mBlobVersion = CommonBlob::getCurrentVersion();
+    // If there's a specific version our callers want, give them that. Otherwise, ask CommonBlob what to do.
+    if(requestedVersion == CommonBlob::version_none) {
+        mBlobVersion = CommonBlob::getCurrentVersion();
+    } else {
+        mBlobVersion = requestedVersion;
+    }
 }
 
 DatabaseCryptoCore::~DatabaseCryptoCore()
@@ -67,6 +74,31 @@ void DatabaseCryptoCore::invalidate()
        mIsValid = false;
 }
 
+//
+// Copy everything from another databasecryptocore
+//
+void DatabaseCryptoCore::initializeFrom(DatabaseCryptoCore& core, uint32 requestedVersion) {
+    if(core.hasMaster()) {
+        mMasterKey = core.mMasterKey;
+        memcpy(mSalt, core.mSalt, sizeof(mSalt));
+        mHaveMaster = core.mHaveMaster;
+    } else {
+        mHaveMaster = false;
+    }
+
+    if(core.isValid()) {
+        importSecrets(core);
+    } else {
+        mIsValid = false;
+    }
+
+    // As the last thing we do, check if we should be changing the version of this blob.
+    if(requestedVersion == CommonBlob::version_none) {
+        mBlobVersion = core.mBlobVersion;
+    } else {
+        mBlobVersion = requestedVersion;
+    }
+}
 
 //
 // Generate new secrets for this crypto core.
@@ -109,8 +141,10 @@ void DatabaseCryptoCore::setup(const DbBlob *blob, const CssmData &passphrase, b
             mBlobVersion = blob->version();
         }
         memcpy(mSalt, blob->salt, sizeof(mSalt));
-    } else
-               Server::active().random(mSalt);
+    } else {
+        MacOSError::check(SecRandomCopyBytes(kSecRandomDefault, sizeof(mSalt), mSalt));
+    }
+
     mMasterKey = deriveDbMasterKey(passphrase);
        mHaveMaster = true;
 }
@@ -136,8 +170,9 @@ void DatabaseCryptoCore::setup(const DbBlob *blob, CssmClient::Key master, bool
             mBlobVersion = blob->version();
         }
         memcpy(mSalt, blob->salt, sizeof(mSalt));
-    } else
-               Server::active().random(mSalt);
+    } else {
+        MacOSError::check(SecRandomCopyBytes(kSecRandomDefault, sizeof(mSalt), mSalt));
+    }
        mMasterKey = master;
        mHaveMaster = true;
 }
@@ -163,9 +198,12 @@ bool DatabaseCryptoCore::get_encryption_key(CssmOwnedData &data)
 //
 bool DatabaseCryptoCore::validatePassphrase(const CssmData &passphrase)
 {
-       assert(hasMaster());
        CssmClient::Key master = deriveDbMasterKey(passphrase);
-       
+    return validateKey(master);
+}
+
+bool DatabaseCryptoCore::validateKey(const CssmClient::Key& master) {
+    assert(hasMaster());
        // to compare master with mMaster, see if they encrypt alike
        StringData probe
                ("Now is the time for all good processes to come to the aid of their kernel.");
@@ -174,7 +212,8 @@ bool DatabaseCryptoCore::validatePassphrase(const CssmData &passphrase)
        cryptor.mode(CSSM_ALGMODE_CBCPadIV8);
        cryptor.padding(CSSM_PADDING_PKCS1);
        uint8 iv[8];    // leave uninitialized; pseudo-random is cool
-       cryptor.initVector(CssmData::wrap(iv));
+    CssmData ivData = CssmData::wrap(iv);
+       cryptor.initVector(ivData);
        
        cryptor.key(master);
        CssmAutoData cipher1(Server::csp().allocator());
@@ -198,7 +237,7 @@ DbBlob *DatabaseCryptoCore::encodeCore(const DbBlob &blobTemplate,
 
     // make a new IV
     uint8 iv[8];
-    Server::active().random(iv);
+    MacOSError::check(SecRandomCopyBytes(kSecRandomDefault, sizeof(iv), iv));
     
     // build the encrypted section blob
     CssmData &encryptionBits = *mEncryptionKey;
@@ -228,9 +267,9 @@ DbBlob *DatabaseCryptoCore::encodeCore(const DbBlob &blobTemplate,
        memcpy(blob->salt, mSalt, sizeof(blob->salt));
     memcpy(blob->iv, iv, sizeof(iv));
     memcpy(blob->publicAclBlob(), publicAcl, publicAcl.length());
-    blob->startCryptoBlob = sizeof(DbBlob) + publicAcl.length();
+    blob->startCryptoBlob = sizeof(DbBlob) + int_cast<size_t, uint32_t>(publicAcl.length());
     memcpy(blob->cryptoBlob(), cryptoBlob, cryptoBlob.length());
-    blob->totalLength = blob->startCryptoBlob + cryptoBlob.length();
+    blob->totalLength = blob->startCryptoBlob + int_cast<size_t, uint32_t>(cryptoBlob.length());
     
     // sign the blob
     CssmData signChunk[] = {
@@ -300,7 +339,7 @@ void DatabaseCryptoCore::decodeCore(const DbBlob *blob, void **privateAclBlob)
     // all checks out; start extracting fields
     if (privateAclBlob) {
         // extract private ACL blob as a separately allocated area
-        uint32 blobLength = decryptedBlob.length() - sizeof(DbBlob::PrivateBlob);
+        uint32 blobLength = (uint32) decryptedBlob.length() - sizeof(DbBlob::PrivateBlob);
         *privateAclBlob = Allocator::standard().malloc(blobLength);
         memcpy(*privateAclBlob, privateBlob->privateAclBlob(), blobLength);
     }
@@ -356,7 +395,7 @@ KeyBlob *DatabaseCryptoCore::encodeKeyCore(const CssmKey &inKey,
                assert(isValid());              // need our database secrets
                
                // create new IV
-               Server::active().random(iv);
+        MacOSError::check(SecRandomCopyBytes(kSecRandomDefault, sizeof(iv), iv));
                
           // use a CMS wrap to encrypt the key
                WrapKey wrap(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE);
@@ -390,9 +429,9 @@ KeyBlob *DatabaseCryptoCore::encodeKeyCore(const CssmKey &inKey,
     blob->wrappedHeader.wrapAlgorithm = wrappedKey.wrapAlgorithm();
     blob->wrappedHeader.wrapMode = wrappedKey.wrapMode();
     memcpy(blob->publicAclBlob(), publicAcl, publicAcl.length());
-    blob->startCryptoBlob = sizeof(KeyBlob) + publicAcl.length();
+    blob->startCryptoBlob = sizeof(KeyBlob) + int_cast<size_t, uint32_t>(publicAcl.length());
     memcpy(blob->cryptoBlob(), wrappedKey.data(), wrappedKey.length());
-    blob->totalLength = blob->startCryptoBlob + wrappedKey.length();
+    blob->totalLength = blob->startCryptoBlob + int_cast<size_t, uint32_t>(wrappedKey.length());
     
        if(inTheClear) {
                /* indicate that this is cleartext for decoding */