]> git.saurik.com Git - apple/security.git/blob - AppleCSPDL/SSKey.cpp
Security-30.1.tar.gz
[apple/security.git] / AppleCSPDL / SSKey.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // SSKey - reference keys for the security server
21 //
22 #include "SSKey.h"
23
24 #include "SSCSPSession.h"
25 #include "SSCSPDLSession.h"
26 #include "SSDatabase.h"
27 #include "SSDLSession.h"
28 #include "KeySchema.h"
29 #include <Security/cssmplugin.h>
30
31 using namespace CssmClient;
32 using namespace SecurityServer;
33
34 // Constructor for a Security Server generated key.
35 SSKey::SSKey(SSCSPSession &session, KeyHandle keyHandle, CssmKey &ioKey,
36 SSDatabase &inSSDatabase, uint32 inKeyAttr,
37 const CssmData *inKeyLabel)
38 : ReferencedKey(session.mSSCSPDLSession),
39 mAllocator(session), mKeyHandle(keyHandle)
40 {
41 CssmKey::Header &header = ioKey.header();
42 if (inKeyAttr & CSSM_KEYATTR_PERMANENT)
43 {
44 if (!inSSDatabase)
45 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE);
46
47 // EncodeKey and store it in the db.
48 CssmDataContainer blob(clientSession().returnAllocator);
49 clientSession().encodeKey(keyHandle, blob);
50
51 assert(header.HeaderVersion == CSSM_KEYHEADER_VERSION);
52 switch (header.KeyClass)
53 {
54 case CSSM_KEYCLASS_PUBLIC_KEY:
55 mRecordType = CSSM_DL_DB_RECORD_PUBLIC_KEY;
56 break;
57 case CSSM_KEYCLASS_PRIVATE_KEY:
58 mRecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY;
59 break;
60 case CSSM_KEYCLASS_SESSION_KEY:
61 mRecordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY;
62 break;
63 default:
64 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
65 }
66
67 CssmData label;
68 if (inKeyLabel)
69 label = *inKeyLabel;
70
71 CssmData none;
72 // We store the keys real CSP guid on disk
73 CssmGuidData creatorGuid(header.CspId);
74 CssmDateData startDate(header.StartDate);
75 CssmDateData endDate(header.EndDate);
76
77 DbAttributes attributes(inSSDatabase);
78 attributes.recordType(mRecordType);
79 attributes.add(KeySchema::KeyClass, mRecordType);
80 attributes.add(KeySchema::PrintName, label);
81 attributes.add(KeySchema::Alias, none);
82 attributes.add(KeySchema::Permanent,
83 header.attribute(CSSM_KEYATTR_PERMANENT));
84 attributes.add(KeySchema::Private,
85 header.attribute(CSSM_KEYATTR_PRIVATE));
86 attributes.add(KeySchema::Modifiable,
87 header.attribute(CSSM_KEYATTR_MODIFIABLE));
88 attributes.add(KeySchema::Label, label);
89 attributes.add(KeySchema::ApplicationTag, none);
90 attributes.add(KeySchema::KeyCreator, creatorGuid);
91 attributes.add(KeySchema::KeyType, header.AlgorithmId);
92 attributes.add(KeySchema::KeySizeInBits, header.LogicalKeySizeInBits);
93 // @@@ Get the real effective key size.
94 attributes.add(KeySchema::EffectiveKeySize, header.LogicalKeySizeInBits);
95 attributes.add(KeySchema::StartDate, startDate);
96 attributes.add(KeySchema::EndDate, endDate);
97 attributes.add(KeySchema::Sensitive,
98 header.attribute(CSSM_KEYATTR_SENSITIVE));
99 attributes.add(KeySchema::AlwaysSensitive,
100 header.attribute(CSSM_KEYATTR_ALWAYS_SENSITIVE));
101 attributes.add(KeySchema::Extractable,
102 header.attribute(CSSM_KEYATTR_EXTRACTABLE));
103 attributes.add(KeySchema::NeverExtractable,
104 header.attribute(CSSM_KEYATTR_NEVER_EXTRACTABLE));
105 attributes.add(KeySchema::Encrypt,
106 header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_ENCRYPT));
107 attributes.add(KeySchema::Decrypt,
108 header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_DECRYPT));
109 attributes.add(KeySchema::Derive,
110 header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_DERIVE));
111 attributes.add(KeySchema::Sign,
112 header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_SIGN));
113 attributes.add(KeySchema::Verify,
114 header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_VERIFY));
115 attributes.add(KeySchema::SignRecover,
116 header.useFor(CSSM_KEYUSE_ANY
117 | CSSM_KEYUSE_SIGN_RECOVER));
118 attributes.add(KeySchema::VerifyRecover,
119 header.useFor(CSSM_KEYUSE_ANY
120 | CSSM_KEYUSE_VERIFY_RECOVER));
121 attributes.add(KeySchema::Wrap,
122 header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_WRAP));
123 attributes.add(KeySchema::Unwrap,
124 header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_UNWRAP));
125
126 // @@@ Fixme
127 mUniqueId = inSSDatabase->insert(mRecordType, &attributes, &blob,
128 true);
129 }
130
131 header.cspGuid(session.plugin.myGuid()); // Set the csp guid to me.
132 makeReferenceKey(mAllocator, keyReference(), ioKey);
133 }
134
135 // Constructor for a key retrived from a Db.
136 SSKey::SSKey(SSDLSession &session, CssmKey &ioKey, SSDatabase &inSSDatabase,
137 const SSUniqueRecord &uniqueId, CSSM_DB_RECORDTYPE recordType,
138 CssmData &keyBlob)
139 : ReferencedKey(session.mSSCSPDLSession),
140 mAllocator(session.allocator()), mKeyHandle(noKey), mUniqueId(uniqueId),
141 mRecordType(recordType)
142 {
143 CssmKey::Header &header = ioKey.header();
144 memset(&header, 0, sizeof(header)); // Clear key header
145
146 if (!mUniqueId || !mUniqueId->database())
147 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
148
149 header.HeaderVersion = CSSM_KEYHEADER_VERSION;
150 switch (mRecordType)
151 {
152 case CSSM_DL_DB_RECORD_PUBLIC_KEY:
153 header.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
154 break;
155 case CSSM_DL_DB_RECORD_PRIVATE_KEY:
156 header.KeyClass = CSSM_KEYCLASS_PRIVATE_KEY;
157 break;
158 case CSSM_DL_DB_RECORD_SYMMETRIC_KEY:
159 header.KeyClass = CSSM_KEYCLASS_SESSION_KEY;
160 break;
161 default:
162 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
163 }
164
165 DbAttributes attributes(mUniqueId->database());
166 attributes.recordType(mRecordType);
167 attributes.add(KeySchema::KeyClass); // 0
168 attributes.add(KeySchema::Permanent); // 1
169 attributes.add(KeySchema::Private); // 2
170 attributes.add(KeySchema::Modifiable); // 3
171 attributes.add(KeySchema::KeyCreator); // 4
172 attributes.add(KeySchema::KeyType); // 5
173 attributes.add(KeySchema::KeySizeInBits); // 6
174 attributes.add(KeySchema::StartDate); // 7
175 attributes.add(KeySchema::EndDate); // 8
176 attributes.add(KeySchema::Sensitive); // 9
177 attributes.add(KeySchema::AlwaysSensitive); // 10
178 attributes.add(KeySchema::Extractable); // 11
179 attributes.add(KeySchema::NeverExtractable); // 12
180 attributes.add(KeySchema::Encrypt); // 13
181 attributes.add(KeySchema::Decrypt); // 14
182 attributes.add(KeySchema::Derive); // 15
183 attributes.add(KeySchema::Sign); // 16
184 attributes.add(KeySchema::Verify); // 17
185 attributes.add(KeySchema::SignRecover); // 18
186 attributes.add(KeySchema::VerifyRecover); // 19
187 attributes.add(KeySchema::Wrap); // 20
188 attributes.add(KeySchema::Unwrap); // 21
189
190 mUniqueId->get(&attributes, NULL);
191
192 // Assert that the mRecordType matches the KeyClass attribute.
193 if (mRecordType != uint32(attributes[0]))
194 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
195
196 header.AlgorithmId = attributes[5]; // KeyType
197 header.LogicalKeySizeInBits = attributes[6]; // KeySizeInBits
198
199 if (attributes[1]) header.setAttribute(CSSM_KEYATTR_PERMANENT);
200 if (attributes[2]) header.setAttribute(CSSM_KEYATTR_PRIVATE);
201 if (attributes[3]) header.setAttribute(CSSM_KEYATTR_MODIFIABLE);
202 if (attributes[9]) header.setAttribute(CSSM_KEYATTR_SENSITIVE);
203 if (attributes[11]) header.setAttribute(CSSM_KEYATTR_EXTRACTABLE);
204 if (attributes[10]) header.setAttribute(CSSM_KEYATTR_ALWAYS_SENSITIVE);
205 if (attributes[12]) header.setAttribute(CSSM_KEYATTR_NEVER_EXTRACTABLE);
206
207 if (attributes[13]) header.usage(CSSM_KEYUSE_ENCRYPT);
208 if (attributes[14]) header.usage(CSSM_KEYUSE_DECRYPT);
209 if (attributes[15]) header.usage(CSSM_KEYUSE_DERIVE);
210 if (attributes[16]) header.usage(CSSM_KEYUSE_SIGN);
211 if (attributes[17]) header.usage(CSSM_KEYUSE_VERIFY);
212 if (attributes[18]) header.usage(CSSM_KEYUSE_SIGN_RECOVER);
213 if (attributes[19]) header.usage(CSSM_KEYUSE_VERIFY_RECOVER);
214 if (attributes[20]) header.usage(CSSM_KEYUSE_WRAP);
215 if (attributes[21]) header.usage(CSSM_KEYUSE_UNWRAP);
216
217 // If all usages are allowed set usage to CSSM_KEYUSE_ANY
218 if (header.usage() == (CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT
219 | CSSM_KEYUSE_DERIVE | CSSM_KEYUSE_SIGN
220 | CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_SIGN_RECOVER
221 | CSSM_KEYUSE_VERIFY_RECOVER | CSSM_KEYUSE_WRAP
222 | CSSM_KEYUSE_UNWRAP))
223 header.usage(CSSM_KEYUSE_ANY);
224
225 if (!attributes[7].size() || !attributes[8].size())
226 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
227
228 header.StartDate = attributes[7].at<CSSM_DATE>(0);
229 header.EndDate = attributes[8].at<CSSM_DATE>(0);
230
231 makeReferenceKey(mAllocator, keyReference(), ioKey);
232 header.cspGuid(session.plugin.myGuid()); // Set the csp guid to me.
233 }
234
235 SSKey::~SSKey()
236 {
237 if (mKeyHandle != noKey)
238 clientSession().releaseKey(mKeyHandle);
239 }
240
241 void
242 SSKey::free(const AccessCredentials *accessCred, CssmKey &ioKey,
243 CSSM_BOOL deleteKey)
244 {
245 freeReferenceKey(mAllocator, ioKey);
246 if (deleteKey)
247 {
248 if (!mUniqueId || !mUniqueId->database())
249 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
250
251 // @@@ Evaluate accessCred against Db acl.
252 // What should we do with accessCred? Reauthenticate
253 // mUniqueId->database()?
254 mUniqueId->deleteRecord();
255 }
256
257 if (mKeyHandle != noKey)
258 {
259 clientSession().releaseKey(mKeyHandle);
260 mKeyHandle = noKey;
261 }
262 }
263
264 SecurityServer::ClientSession &
265 SSKey::clientSession()
266 {
267 return keyPool<SSCSPDLSession>().clientSession();
268 }
269
270 KeyHandle
271 SSKey::keyHandle()
272 {
273 if (mKeyHandle == noKey)
274 {
275 // Deal with uninstantiated keys.
276 if (!mUniqueId || !mUniqueId->database())
277 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
278
279 CssmDataContainer blob;
280 mUniqueId->get(NULL, &blob);
281 CssmKey::Header dummyHeader; // @@@ Unused
282 mKeyHandle =
283 clientSession().decodeKey(mUniqueId->database().dbHandle(), blob,
284 dummyHeader);
285
286 // @@@ Check decoded header against returned header
287 }
288
289 return mKeyHandle;
290 }
291
292 //
293 // ACL retrieval and change operations
294 //
295 void
296 SSKey::getOwner(CSSM_ACL_OWNER_PROTOTYPE &owner, CssmAllocator &allocator)
297 {
298 clientSession().getKeyOwner(keyHandle(), AclOwnerPrototype::overlay(owner),
299 allocator);
300 }
301
302 void
303 SSKey::changeOwner(const AccessCredentials &accessCred,
304 const AclOwnerPrototype &newOwner)
305 {
306 clientSession().changeKeyOwner(keyHandle(), accessCred, newOwner);
307 if (mUniqueId == true)
308 {
309 // The key is persistant, make the change on disk.
310 CssmDataContainer keyBlob(clientSession().returnAllocator);
311 clientSession().encodeKey(keyHandle(), keyBlob);
312 mUniqueId->modify(mRecordType, NULL, &keyBlob,
313 CSSM_DB_MODIFY_ATTRIBUTE_NONE);
314 }
315 }
316
317 void
318 SSKey::getAcl(const char *selectionTag, uint32 &numberOfAclInfos,
319 AclEntryInfo *&aclInfos, CssmAllocator &allocator)
320 {
321 clientSession().getKeyAcl(keyHandle(), selectionTag, numberOfAclInfos,
322 aclInfos, allocator);
323 }
324
325 void
326 SSKey::changeAcl(const AccessCredentials &accessCred, const AclEdit &aclEdit)
327 {
328 clientSession().changeKeyAcl(keyHandle(), accessCred, aclEdit);
329 if (mUniqueId == true)
330 {
331 // The key is persistant, make the change on disk.
332 CssmDataContainer keyBlob(clientSession().returnAllocator);
333 clientSession().encodeKey(keyHandle(), keyBlob);
334 mUniqueId->modify(mRecordType, NULL, &keyBlob,
335 CSSM_DB_MODIFY_ATTRIBUTE_NONE);
336 }
337 }