]> git.saurik.com Git - apple/securityd.git/blob - src/localdatabase.cpp
f486373c492863851d676ba480aa5974b92be913
[apple/securityd.git] / src / localdatabase.cpp
1 /*
2 * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26
27 //
28 // localdatabase - locally implemented database using internal CSP cryptography
29 //
30 #include "localdatabase.h"
31 #include "agentquery.h"
32 #include "localkey.h"
33 #include "server.h"
34 #include "session.h"
35 #include <security_agent_client/agentclient.h>
36 #include <security_cdsa_utilities/acl_any.h> // for default owner ACLs
37 #include <security_cdsa_client/wrapkey.h>
38 #include <security_cdsa_client/genkey.h>
39 #include <security_cdsa_client/signclient.h>
40 #include <security_cdsa_client/cryptoclient.h>
41 #include <security_cdsa_client/macclient.h>
42 #include <security_utilities/endian.h>
43
44
45 //
46 // Create a Database object from initial parameters (create operation)
47 //
48 LocalDatabase::LocalDatabase(Process &proc)
49 : Database(proc)
50 {
51 }
52
53
54 static inline LocalKey &myKey(Key &key)
55 {
56 return safer_cast<LocalKey &>(key);
57 }
58
59
60 //
61 // Key inquiries
62 //
63 CSSM_KEY_SIZE LocalDatabase::queryKeySize(Key &key)
64 {
65 CssmClient::Key theKey(Server::csp(), myKey(key));
66 return theKey.sizeInBits();
67 }
68
69
70 //
71 // Signatures and MACs
72 //
73 void LocalDatabase::generateSignature(const Context &context, Key &key,
74 CSSM_ALGORITHMS signOnlyAlgorithm, const CssmData &data, CssmData &signature)
75 {
76 context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
77 key.validate(CSSM_ACL_AUTHORIZATION_SIGN, context);
78 CssmClient::Sign signer(Server::csp(), context.algorithm(), signOnlyAlgorithm);
79 signer.override(context);
80 signer.sign(data, signature);
81 }
82
83 void LocalDatabase::verifySignature(const Context &context, Key &key,
84 CSSM_ALGORITHMS verifyOnlyAlgorithm, const CssmData &data, const CssmData &signature)
85 {
86 context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
87 CssmClient::Verify verifier(Server::csp(), context.algorithm(), verifyOnlyAlgorithm);
88 verifier.override(context);
89 verifier.verify(data, signature);
90 }
91
92 void LocalDatabase::generateMac(const Context &context, Key &key,
93 const CssmData &data, CssmData &mac)
94 {
95 context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
96 key.validate(CSSM_ACL_AUTHORIZATION_MAC, context);
97 CssmClient::GenerateMac signer(Server::csp(), context.algorithm());
98 signer.override(context);
99 signer.sign(data, mac);
100 }
101
102 void LocalDatabase::verifyMac(const Context &context, Key &key,
103 const CssmData &data, const CssmData &mac)
104 {
105 context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
106 key.validate(CSSM_ACL_AUTHORIZATION_MAC, context);
107 CssmClient::VerifyMac verifier(Server::csp(), context.algorithm());
108 verifier.override(context);
109 verifier.verify(data, mac);
110 }
111
112
113 //
114 // Encryption/decryption
115 //
116 void LocalDatabase::encrypt(const Context &context, Key &key,
117 const CssmData &clear, CssmData &cipher)
118 {
119 context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
120 key.validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context);
121 CssmClient::Encrypt cryptor(Server::csp(), context.algorithm());
122 cryptor.override(context);
123 CssmData remData;
124 size_t totalLength = cryptor.encrypt(clear, cipher, remData);
125 // shouldn't need remData - if an algorithm REQUIRES this, we'd have to ship it
126 if (remData)
127 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
128 cipher.length(totalLength);
129 }
130
131 void LocalDatabase::decrypt(const Context &context, Key &key,
132 const CssmData &cipher, CssmData &clear)
133 {
134 context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
135 key.validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context);
136 CssmClient::Decrypt cryptor(Server::csp(), context.algorithm());
137 cryptor.override(context);
138 CssmData remData;
139 size_t totalLength = cryptor.decrypt(cipher, clear, remData);
140 // shouldn't need remData - if an algorithm REQUIRES this, we'd have to ship it
141 if (remData)
142 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
143 clear.length(totalLength);
144 }
145
146
147 //
148 // Key generation and derivation.
149 // Currently, we consider symmetric key generation to be fast, but
150 // asymmetric key generation to be (potentially) slow.
151 //
152 void LocalDatabase::generateKey(const Context &context,
153 const AccessCredentials *cred, const AclEntryPrototype *owner,
154 uint32 usage, uint32 attrs, RefPointer<Key> &newKey)
155 {
156 // prepare a context
157 CssmClient::GenerateKey generate(Server::csp(), context.algorithm());
158 generate.override(context);
159
160 // generate key
161 // @@@ turn "none" return into reference if permanent (only)
162 CssmKey key;
163 generate(key, Key::KeySpec(usage, attrs));
164
165 // register and return the generated key
166 newKey = makeKey(key, attrs & Key::managedAttributes, owner);
167 }
168
169 void LocalDatabase::generateKey(const Context &context,
170 const AccessCredentials *cred, const AclEntryPrototype *owner,
171 uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs,
172 RefPointer<Key> &publicKey, RefPointer<Key> &privateKey)
173 {
174 // prepare a context
175 CssmClient::GenerateKey generate(Server::csp(), context.algorithm());
176 generate.override(context);
177
178 // this may take a while; let our server object know
179 Server::active().longTermActivity();
180
181 // generate keys
182 // @@@ turn "none" return into reference if permanent (only)
183 CssmKey pubKey, privKey;
184 generate(pubKey, Key::KeySpec(pubUsage, pubAttrs),
185 privKey, Key::KeySpec(privUsage, privAttrs));
186
187 // register and return the generated keys
188 publicKey = makeKey(pubKey, pubAttrs & Key::managedAttributes, owner);
189 privateKey = makeKey(privKey, privAttrs & Key::managedAttributes, owner);
190 }
191
192 RefPointer<Key> LocalDatabase::deriveKey(const Context &context, Key *baseKey,
193 const AccessCredentials *cred, const AclEntryPrototype *owner,
194 CssmData *param, uint32 usage, uint32 attrs)
195 {
196 // prepare a key-derivation context
197 if (baseKey) {
198 baseKey->validate(CSSM_ACL_AUTHORIZATION_DERIVE, cred);
199 context.replace(CSSM_ATTRIBUTE_KEY, myKey(*baseKey).cssmKey());
200 }
201 CssmClient::DeriveKey derive(Server::csp(), context.algorithm(), CSSM_ALGID_NONE);
202 derive.override(context);
203
204 // derive key
205 // @@@ turn "none" return into reference if permanent (only)
206 CssmKey key;
207 derive(param, Key::KeySpec(usage, attrs), key);
208
209 // register and return the generated key
210 return makeKey(key, attrs & Key::managedAttributes, owner);
211 }
212
213
214 //
215 // Key wrapping and unwrapping.
216 // Note that the key argument (the key in the context) is optional because of the special
217 // case of "cleartext" (null algorithm) wrapping for import/export.
218 //
219
220 void LocalDatabase::wrapKey(const Context &context, Key *key,
221 Key &keyToBeWrapped, const AccessCredentials *cred,
222 const CssmData &descriptiveData, CssmKey &wrappedKey)
223 {
224 keyToBeWrapped.validate(context.algorithm() == CSSM_ALGID_NONE ?
225 CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR : CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED,
226 cred);
227 if(!(keyToBeWrapped.attributes() & CSSM_KEYATTR_EXTRACTABLE)) {
228 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
229 }
230 if (key) {
231 context.replace(CSSM_ATTRIBUTE_KEY, myKey(*key).cssmKey());
232 key->validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context);
233 }
234 CssmClient::WrapKey wrap(Server::csp(), context.algorithm());
235 wrap.override(context);
236 wrap.cred(const_cast<AccessCredentials *>(cred)); //@@@ const madness - fix in client/pod
237 wrap(myKey(keyToBeWrapped), wrappedKey, &descriptiveData);
238 }
239
240 RefPointer<Key> LocalDatabase::unwrapKey(const Context &context, Key *key,
241 const AccessCredentials *cred, const AclEntryPrototype *owner,
242 uint32 usage, uint32 attrs, const CssmKey wrappedKey,
243 Key *publicKey, CssmData *descriptiveData)
244 {
245 if (key) {
246 context.replace(CSSM_ATTRIBUTE_KEY, myKey(*key).cssmKey());
247 key->validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context);
248 }
249 CssmClient::UnwrapKey unwrap(Server::csp(), context.algorithm());
250 unwrap.override(context);
251 CssmKey unwrappedKey;
252 unwrap.cred(const_cast<AccessCredentials *>(cred)); //@@@ const madness - fix in client/pod
253 if (owner) {
254 AclEntryInput ownerInput(*owner); //@@@ const trouble - fix in client/pod
255 unwrap.aclEntry(ownerInput);
256 }
257
258 // @@@ Invoking conversion operator to CssmKey & on *publicKey and take the address of the result.
259 unwrap(wrappedKey, Key::KeySpec(usage, attrs), unwrappedKey,
260 descriptiveData, publicKey ? &static_cast<const CssmKey &>(myKey(*publicKey)) : NULL);
261
262 return makeKey(unwrappedKey, attrs & Key::managedAttributes, owner);
263 }
264
265
266 //
267 // Miscellaneous CSSM functions
268 //
269 uint32 LocalDatabase::getOutputSize(const Context &context, Key &key, uint32 inputSize, bool encrypt)
270 {
271 // We're fudging here somewhat, since the context can be any type.
272 // ctx.override will fix the type, and no-one's the wiser.
273 context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
274 CssmClient::Digest ctx(Server::csp(), context.algorithm());
275 ctx.override(context);
276 return ctx.getOutputSize(inputSize, encrypt);
277 }
278
279
280 //
281 // (Re-)Authenticate the database. This changes the stored credentials.
282 //
283 void LocalDatabase::authenticate(const AccessCredentials *cred)
284 {
285 StLock<Mutex> _(common());
286 AccessCredentials *newCred = DataWalkers::copy(cred, Allocator::standard());
287 Allocator::standard().free(mCred);
288 mCred = newCred;
289 }