2 * Copyright (c) 2000-2004,2006,2011,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@
26 // ssclient - SecurityServer client interface library
32 namespace SecurityServer
{
34 uint32
CommonBlob::getCurrentVersion() {
35 uint32 ret
= version_MacOS_10_0
;
36 // If the integrity protections are turned on, use version_partition.
37 // else, use version_MacOS_10_0.
38 CFTypeRef integrity
= (CFNumberRef
)CFPreferencesCopyValue(CFSTR("KeychainIntegrity"), CFSTR("com.apple.security"), kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
);
39 if (integrity
&& CFGetTypeID(integrity
) == CFBooleanGetTypeID()) {
40 bool integrityProtections
= CFBooleanGetValue((CFBooleanRef
)integrity
);
42 if(integrityProtections
) {
43 secnotice("integrity", "creating a partition keychain; global is on");
44 ret
= version_partition
;
46 secnotice("integrity", "creating a old-style keychain; global is off");
47 ret
= version_MacOS_10_0
;
51 secnotice("integrity", "global integrity not set, defaulting to on");
52 ret
= version_partition
;
58 uint32
CommonBlob::getCurrentVersionForDb(const char* dbName
) {
59 // Currently, the scheme is as follows:
60 // in ~/Library/Keychains:
63 // version_MacOS_10_0`
65 if(pathInHomeLibraryKeychains(dbName
)) {
66 return CommonBlob::getCurrentVersion();
69 secnotice("integrity", "outside ~/Library/Keychains/; creating a old-style keychain");
70 return version_MacOS_10_0
;
73 bool CommonBlob::pathInHomeLibraryKeychains(const string
& path
) {
74 // We need to check if this path is in Some User's ~/Library/Keychains directory.
75 // At this level, there's no great way of discovering what's actually a
76 // user's home directory, so instead let's look for anything under
77 // ./Library/Keychains/ that isn't /Library/Keychains or /System/Library/Keychains.
79 string libraryKeychains
= "/Library/Keychains";
80 string systemLibraryKeychains
= "/System/Library/Keychains";
82 bool inALibraryKeychains
= (string::npos
!= path
.find(libraryKeychains
));
83 bool inRootLibraryKeychains
= (0 == path
.find(libraryKeychains
));
84 bool inSystemLibraryKeychains
= (0 == path
.find(systemLibraryKeychains
));
86 return (inALibraryKeychains
&& !inRootLibraryKeychains
&& !inSystemLibraryKeychains
);
89 void CommonBlob::initialize()
93 this->blobVersion
= getCurrentVersion();
97 // Initialize the blob header for a given version
99 void CommonBlob::initialize(uint32 version
)
103 secinfo("integrity", "creating a keychain with version %d", version
);
104 this->blobVersion
= version
;
109 // Verify the blob header for basic sane-ness.
111 bool CommonBlob::isValid() const
113 return magic
== magicNumber
;
116 void CommonBlob::validate(CSSM_RETURN failureCode
) const
119 CssmError::throwMe(failureCode
);
123 * This string is placed in KeyBlob.blobSignature to indicate a cleartext
126 static const char clearPubKeySig
[] = "Cleartext public key";
128 bool KeyBlob::isClearText()
130 return (memcmp(blobSignature
, clearPubKeySig
,
131 sizeof(blobSignature
)) == 0);
134 void KeyBlob::setClearTextSignature()
136 memmove(blobSignature
, clearPubKeySig
, sizeof(blobSignature
));
140 // Implementation of a "system keychain unlock key store"
142 SystemKeychainKey::SystemKeychainKey(const char *path
)
143 : mPath(path
), mValid(false)
145 // explicitly set up a key header for a raw 3DES key
146 CssmKey::Header
&hdr
= mKey
.header();
147 hdr
.blobType(CSSM_KEYBLOB_RAW
);
148 hdr
.blobFormat(CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
);
149 hdr
.keyClass(CSSM_KEYCLASS_SESSION_KEY
);
150 hdr
.algorithm(CSSM_ALGID_3DES_3KEY_EDE
);
152 hdr
.KeyUsage
= CSSM_KEYUSE_ANY
;
153 mKey
= CssmData::wrap(mBlob
.masterKey
);
156 SystemKeychainKey::~SystemKeychainKey()
160 bool SystemKeychainKey::matches(const DbBlob::Signature
&signature
)
162 return update() && signature
== mBlob
.signature
;
165 CssmKey
& SystemKeychainKey::key()
173 bool SystemKeychainKey::update()
175 // if we checked recently, just assume it's okay
176 if (mValid
&& mUpdateThreshold
> Time::now())
181 if (::stat(mPath
.c_str(), &st
)) {
182 // something wrong with the file; can't use it
183 mUpdateThreshold
= Time::now() + Time::Interval(checkDelay
);
184 return mValid
= false;
186 if (mValid
&& Time::Absolute(st
.st_mtimespec
) == mCachedDate
)
188 mUpdateThreshold
= Time::now() + Time::Interval(checkDelay
);
191 secnotice("syskc", "reading system unlock record from %s", mPath
.c_str());
192 UnixPlusPlus::AutoFileDesc
fd(mPath
, O_RDONLY
);
193 if (fd
.read(mBlob
) != sizeof(mBlob
))
195 if (mBlob
.isValid()) {
196 mCachedDate
= st
.st_mtimespec
;
197 return mValid
= true;
199 return mValid
= false;
201 secnotice("syskc", "system unlock record not available");
206 bool SystemKeychainKey::valid()
213 } // end namespace SecurityServer
215 } // end namespace Security