2 * Copyright (c) 2004,2008 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 // SDKey - reference keys for the security server
30 #include "SDCSPSession.h"
31 #include "SDCSPDLSession.h"
32 #include "SDDLSession.h"
33 #include <security_cdsa_utilities/KeySchema.h>
34 #include <security_cdsa_utilities/cssmdb.h>
35 #include <security_cdsa_plugin/cssmplugin.h>
37 using namespace CssmClient
;
38 using namespace SecurityServer
;
40 // Constructor for a Security Server generated key.
41 SDKey::SDKey(SDCSPSession
&session
, KeyHandle hKey
, CssmKey
&ioKey
,
42 CSSM_DB_HANDLE inDBHandle
, uint32 inKeyAttr
,
43 const CssmData
*inKeyLabel
)
44 : ReferencedKey(session
.mSDCSPDLSession
),
45 mAllocator(session
), mKeyHandle(hKey
),
46 mClientSession(session
.clientSession())
48 CssmKey::Header
&header
= ioKey
.header();
50 if (inKeyAttr
& CSSM_KEYATTR_PERMANENT
)
53 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE
);
55 // EncodeKey and store it in the db.
56 CssmDataContainer
blob(mAllocator
);
57 clientSession().encodeKey(keyHandle
, blob
);
59 assert(header
.HeaderVersion
== CSSM_KEYHEADER_VERSION
);
60 switch (header
.KeyClass
)
62 case CSSM_KEYCLASS_PUBLIC_KEY
:
63 mRecordType
= CSSM_DL_DB_RECORD_PUBLIC_KEY
;
65 case CSSM_KEYCLASS_PRIVATE_KEY
:
66 mRecordType
= CSSM_DL_DB_RECORD_PRIVATE_KEY
;
68 case CSSM_KEYCLASS_SESSION_KEY
:
69 mRecordType
= CSSM_DL_DB_RECORD_SYMMETRIC_KEY
;
72 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
80 // We store the keys real CSP guid on disk
81 CssmGuidData
creatorGuid(header
.CspId
);
82 CssmDateData
startDate(header
.StartDate
);
83 CssmDateData
endDate(header
.EndDate
);
85 DbAttributes
attributes(inDBHandle
);
86 attributes
.recordType(mRecordType
);
87 attributes
.add(KeySchema::KeyClass
, mRecordType
);
88 attributes
.add(KeySchema::PrintName
, label
);
89 attributes
.add(KeySchema::Alias
, none
);
90 attributes
.add(KeySchema::Permanent
,
91 header
.attribute(CSSM_KEYATTR_PERMANENT
));
92 attributes
.add(KeySchema::Private
,
93 header
.attribute(CSSM_KEYATTR_PRIVATE
));
94 attributes
.add(KeySchema::Modifiable
,
95 header
.attribute(CSSM_KEYATTR_MODIFIABLE
));
96 attributes
.add(KeySchema::Label
, label
);
97 attributes
.add(KeySchema::ApplicationTag
, none
);
98 attributes
.add(KeySchema::KeyCreator
, creatorGuid
);
99 attributes
.add(KeySchema::KeyType
, header
.AlgorithmId
);
100 attributes
.add(KeySchema::KeySizeInBits
, header
.LogicalKeySizeInBits
);
101 // @@@ Get the real effective key size.
102 attributes
.add(KeySchema::EffectiveKeySize
, header
.LogicalKeySizeInBits
);
103 attributes
.add(KeySchema::StartDate
, startDate
);
104 attributes
.add(KeySchema::EndDate
, endDate
);
105 attributes
.add(KeySchema::Sensitive
,
106 header
.attribute(CSSM_KEYATTR_SENSITIVE
));
107 attributes
.add(KeySchema::AlwaysSensitive
,
108 header
.attribute(CSSM_KEYATTR_ALWAYS_SENSITIVE
));
109 attributes
.add(KeySchema::Extractable
,
110 header
.attribute(CSSM_KEYATTR_EXTRACTABLE
));
111 attributes
.add(KeySchema::NeverExtractable
,
112 header
.attribute(CSSM_KEYATTR_NEVER_EXTRACTABLE
));
113 attributes
.add(KeySchema::Encrypt
,
114 header
.useFor(CSSM_KEYUSE_ANY
| CSSM_KEYUSE_ENCRYPT
));
115 attributes
.add(KeySchema::Decrypt
,
116 header
.useFor(CSSM_KEYUSE_ANY
| CSSM_KEYUSE_DECRYPT
));
117 attributes
.add(KeySchema::Derive
,
118 header
.useFor(CSSM_KEYUSE_ANY
| CSSM_KEYUSE_DERIVE
));
119 attributes
.add(KeySchema::Sign
,
120 header
.useFor(CSSM_KEYUSE_ANY
| CSSM_KEYUSE_SIGN
));
121 attributes
.add(KeySchema::Verify
,
122 header
.useFor(CSSM_KEYUSE_ANY
| CSSM_KEYUSE_VERIFY
));
123 attributes
.add(KeySchema::SignRecover
,
124 header
.useFor(CSSM_KEYUSE_ANY
125 | CSSM_KEYUSE_SIGN_RECOVER
));
126 attributes
.add(KeySchema::VerifyRecover
,
127 header
.useFor(CSSM_KEYUSE_ANY
128 | CSSM_KEYUSE_VERIFY_RECOVER
));
129 attributes
.add(KeySchema::Wrap
,
130 header
.useFor(CSSM_KEYUSE_ANY
| CSSM_KEYUSE_WRAP
));
131 attributes
.add(KeySchema::Unwrap
,
132 header
.useFor(CSSM_KEYUSE_ANY
| CSSM_KEYUSE_UNWRAP
));
135 mUniqueId
= inDBHandle
->insert(mRecordType
, &attributes
, &blob
,
140 header
.cspGuid(session
.plugin
.myGuid()); // Set the csp guid to me.
141 makeReferenceKey(mAllocator
, keyReference(), ioKey
);
144 // Constructor for a key retrived from a Db.
145 SDKey::SDKey(SDDLSession
&session
, CssmKey
&ioKey
, KeyHandle hKey
, CSSM_DB_HANDLE inDBHandle
,
146 RecordHandle record
, CSSM_DB_RECORDTYPE recordType
,
148 : ReferencedKey(session
.mSDCSPDLSession
),
149 mAllocator(session
.allocator()), mKeyHandle(hKey
), mRecord(record
),
150 mClientSession(session
.clientSession())
152 CssmKey::Header
&header
= ioKey
.header();
154 memset(&header
, 0, sizeof(header
)); // Clear key header
156 if (!mUniqueId
|| !mUniqueId
->database())
157 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
159 header
.HeaderVersion
= CSSM_KEYHEADER_VERSION
;
162 case CSSM_DL_DB_RECORD_PUBLIC_KEY
:
163 header
.KeyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
165 case CSSM_DL_DB_RECORD_PRIVATE_KEY
:
166 header
.KeyClass
= CSSM_KEYCLASS_PRIVATE_KEY
;
168 case CSSM_DL_DB_RECORD_SYMMETRIC_KEY
:
169 header
.KeyClass
= CSSM_KEYCLASS_SESSION_KEY
;
172 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
175 DbAttributes
attributes(mUniqueId
->database());
176 attributes
.recordType(mRecordType
);
177 attributes
.add(KeySchema::KeyClass
); // 0
178 attributes
.add(KeySchema::Permanent
); // 1
179 attributes
.add(KeySchema::Private
); // 2
180 attributes
.add(KeySchema::Modifiable
); // 3
181 attributes
.add(KeySchema::KeyCreator
); // 4
182 attributes
.add(KeySchema::KeyType
); // 5
183 attributes
.add(KeySchema::KeySizeInBits
); // 6
184 attributes
.add(KeySchema::StartDate
); // 7
185 attributes
.add(KeySchema::EndDate
); // 8
186 attributes
.add(KeySchema::Sensitive
); // 9
187 attributes
.add(KeySchema::AlwaysSensitive
); // 10
188 attributes
.add(KeySchema::Extractable
); // 11
189 attributes
.add(KeySchema::NeverExtractable
); // 12
190 attributes
.add(KeySchema::Encrypt
); // 13
191 attributes
.add(KeySchema::Decrypt
); // 14
192 attributes
.add(KeySchema::Derive
); // 15
193 attributes
.add(KeySchema::Sign
); // 16
194 attributes
.add(KeySchema::Verify
); // 17
195 attributes
.add(KeySchema::SignRecover
); // 18
196 attributes
.add(KeySchema::VerifyRecover
); // 19
197 attributes
.add(KeySchema::Wrap
); // 20
198 attributes
.add(KeySchema::Unwrap
); // 21
200 mUniqueId
->get(&attributes
, NULL
);
202 // Assert that the mRecordType matches the KeyClass attribute.
203 if (mRecordType
!= uint32(attributes
[0]))
204 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
206 header
.AlgorithmId
= attributes
[5]; // KeyType
207 header
.LogicalKeySizeInBits
= attributes
[6]; // KeySizeInBits
209 if (attributes
[1]) header
.setAttribute(CSSM_KEYATTR_PERMANENT
);
210 if (attributes
[2]) header
.setAttribute(CSSM_KEYATTR_PRIVATE
);
211 if (attributes
[3]) header
.setAttribute(CSSM_KEYATTR_MODIFIABLE
);
212 if (attributes
[9]) header
.setAttribute(CSSM_KEYATTR_SENSITIVE
);
213 if (attributes
[11]) header
.setAttribute(CSSM_KEYATTR_EXTRACTABLE
);
214 if (attributes
[10]) header
.setAttribute(CSSM_KEYATTR_ALWAYS_SENSITIVE
);
215 if (attributes
[12]) header
.setAttribute(CSSM_KEYATTR_NEVER_EXTRACTABLE
);
217 if (attributes
[13]) header
.usage(CSSM_KEYUSE_ENCRYPT
);
218 if (attributes
[14]) header
.usage(CSSM_KEYUSE_DECRYPT
);
219 if (attributes
[15]) header
.usage(CSSM_KEYUSE_DERIVE
);
220 if (attributes
[16]) header
.usage(CSSM_KEYUSE_SIGN
);
221 if (attributes
[17]) header
.usage(CSSM_KEYUSE_VERIFY
);
222 if (attributes
[18]) header
.usage(CSSM_KEYUSE_SIGN_RECOVER
);
223 if (attributes
[19]) header
.usage(CSSM_KEYUSE_VERIFY_RECOVER
);
224 if (attributes
[20]) header
.usage(CSSM_KEYUSE_WRAP
);
225 if (attributes
[21]) header
.usage(CSSM_KEYUSE_UNWRAP
);
227 // If all usages are allowed set usage to CSSM_KEYUSE_ANY
228 if (header
.usage() == (CSSM_KEYUSE_ENCRYPT
| CSSM_KEYUSE_DECRYPT
229 | CSSM_KEYUSE_DERIVE
| CSSM_KEYUSE_SIGN
230 | CSSM_KEYUSE_VERIFY
| CSSM_KEYUSE_SIGN_RECOVER
231 | CSSM_KEYUSE_VERIFY_RECOVER
| CSSM_KEYUSE_WRAP
232 | CSSM_KEYUSE_UNWRAP
))
233 header
.usage(CSSM_KEYUSE_ANY
);
235 if (!attributes
[7].size() || !attributes
[8].size())
236 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
238 header
.StartDate
= attributes
[7].at
<CSSM_DATE
>(0);
239 header
.EndDate
= attributes
[8].at
<CSSM_DATE
>(0);
242 makeReferenceKey(mAllocator
, keyReference(), ioKey
);
243 header
.cspGuid(session
.plugin
.myGuid()); // Set the csp guid to me.
248 if (mKeyHandle
!= noKey
)
249 clientSession().releaseKey(mKeyHandle
);
253 SDKey::free(const AccessCredentials
*accessCred
, CssmKey
&ioKey
,
256 // @@@ We need a new freeKey(const AccessCredentials *accessCred, CSSM_HANDLE key, CSSM_BOOL deleteKey)
257 // In the client library
258 freeReferenceKey(mAllocator
, ioKey
);
261 if (!mRecord
|| !mDatabase
)
262 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
264 // @@@ Evaluate accessCred against Db acl.
265 // What should we do with accessCred? Reauthenticate
266 // mUniqueId->database()?
267 clientSession().deleteRecord(ClientSession::toIPCHandle(mDatabase
), ClientSession::toIPCHandle(mRecord
));
270 if (mKeyHandle
!= noKey
)
272 clientSession().releaseKey(mKeyHandle
);
277 SecurityServer::ClientSession
&
278 SDKey::clientSession()
280 return mClientSession
;
283 KeyHandle
SDKey::optionalKeyHandle() const
291 if (mKeyHandle
== noKey
)
294 // Deal with uninstantiated keys.
295 if (!mUniqueId
|| !mUniqueId
->database())
296 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
298 CssmDataContainer
blob(mAllocator
);
299 mUniqueId
->get(NULL
, &blob
);
300 CssmKey::Header dummyHeader
; // @@@ Unused
302 clientSession().decodeKey(mUniqueId
->database().dbHandle(), blob
,
305 // @@@ Check decoded header against returned header
315 // ACL retrieval and change operations
318 SDKey::getOwner(CSSM_ACL_OWNER_PROTOTYPE
&owner
, Allocator
&allocator
)
320 clientSession().getKeyOwner(keyHandle(), AclOwnerPrototype::overlay(owner
),
325 SDKey::changeOwner(const AccessCredentials
&accessCred
,
326 const AclOwnerPrototype
&newOwner
)
328 clientSession().changeKeyOwner(keyHandle(), accessCred
, newOwner
);
332 SDKey::getAcl(const char *selectionTag
, uint32
&numberOfAclInfos
,
333 AclEntryInfo
*&aclInfos
, Allocator
&allocator
)
335 clientSession().getKeyAcl(keyHandle(), selectionTag
, numberOfAclInfos
,
336 aclInfos
, allocator
);
340 SDKey::changeAcl(const AccessCredentials
&accessCred
, const AclEdit
&aclEdit
)
342 clientSession().changeKeyAcl(keyHandle(), accessCred
, aclEdit
);