]> git.saurik.com Git - apple/security.git/blob - securityd/src/localdatabase.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / securityd / src / localdatabase.cpp
1 /*
2 * Copyright (c) 2004,2006,2008 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 //
26 // localdatabase - locally implemented database using internal CSP cryptography
27 //
28 #include "localdatabase.h"
29 #include "agentquery.h"
30 #include "localkey.h"
31 #include "server.h"
32 #include "session.h"
33 #include <security_cdsa_utilities/acl_any.h> // for default owner ACLs
34 #include <security_cdsa_client/wrapkey.h>
35 #include <security_cdsa_client/genkey.h>
36 #include <security_cdsa_client/signclient.h>
37 #include <security_cdsa_client/cryptoclient.h>
38 #include <security_cdsa_client/macclient.h>
39 #include <security_utilities/endian.h>
40
41
42 //
43 // Create a Database object from initial parameters (create operation)
44 //
45 LocalDatabase::LocalDatabase(Process &proc)
46 : Database(proc)
47 {
48 }
49
50
51 static inline LocalKey &myKey(Key &key)
52 {
53 return safer_cast<LocalKey &>(key);
54 }
55
56
57 //
58 // Key inquiries
59 //
60 void LocalDatabase::queryKeySizeInBits(Key &key, CssmKeySize &result)
61 {
62 CssmClient::Key theKey(Server::csp(), myKey(key));
63 result = theKey.sizeInBits();
64 }
65
66
67 //
68 // Signatures and MACs
69 //
70 void LocalDatabase::generateSignature(const Context &context, Key &key,
71 CSSM_ALGORITHMS signOnlyAlgorithm, const CssmData &data, CssmData &signature)
72 {
73 context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
74 key.validate(CSSM_ACL_AUTHORIZATION_SIGN, context);
75 CssmClient::Sign signer(Server::csp(), context.algorithm(), signOnlyAlgorithm);
76 signer.override(context);
77 signer.sign(data, signature);
78 }
79
80 void LocalDatabase::verifySignature(const Context &context, Key &key,
81 CSSM_ALGORITHMS verifyOnlyAlgorithm, const CssmData &data, const CssmData &signature)
82 {
83 context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
84 CssmClient::Verify verifier(Server::csp(), context.algorithm(), verifyOnlyAlgorithm);
85 verifier.override(context);
86 verifier.verify(data, signature);
87 }
88
89 void LocalDatabase::generateMac(const Context &context, Key &key,
90 const CssmData &data, CssmData &mac)
91 {
92 context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
93 key.validate(CSSM_ACL_AUTHORIZATION_MAC, context);
94 CssmClient::GenerateMac signer(Server::csp(), context.algorithm());
95 signer.override(context);
96 signer.sign(data, mac);
97 }
98
99 void LocalDatabase::verifyMac(const Context &context, Key &key,
100 const CssmData &data, const CssmData &mac)
101 {
102 context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
103 key.validate(CSSM_ACL_AUTHORIZATION_MAC, context);
104 CssmClient::VerifyMac verifier(Server::csp(), context.algorithm());
105 verifier.override(context);
106 verifier.verify(data, mac);
107 }
108
109
110 //
111 // Encryption/decryption
112 //
113 void LocalDatabase::encrypt(const Context &context, Key &key,
114 const CssmData &clear, CssmData &cipher)
115 {
116 context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
117 key.validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context);
118 CssmClient::Encrypt cryptor(Server::csp(), context.algorithm());
119 cryptor.override(context);
120 CssmData remData;
121 size_t totalLength = cryptor.encrypt(clear, cipher, remData);
122 // shouldn't need remData - if an algorithm REQUIRES this, we'd have to ship it
123 if (remData)
124 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
125 cipher.length(totalLength);
126 }
127
128 void LocalDatabase::decrypt(const Context &context, Key &key,
129 const CssmData &cipher, CssmData &clear)
130 {
131 context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
132 key.validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context);
133 CssmClient::Decrypt cryptor(Server::csp(), context.algorithm());
134 cryptor.override(context);
135 CssmData remData;
136 size_t totalLength = cryptor.decrypt(cipher, clear, remData);
137 // shouldn't need remData - if an algorithm REQUIRES this, we'd have to ship it
138 if (remData)
139 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
140 clear.length(totalLength);
141 }
142
143
144 //
145 // Key generation and derivation.
146 // Currently, we consider symmetric key generation to be fast, but
147 // asymmetric key generation to be (potentially) slow.
148 //
149 void LocalDatabase::generateKey(const Context &context,
150 const AccessCredentials *cred, const AclEntryPrototype *owner,
151 uint32 usage, uint32 attrs, RefPointer<Key> &newKey)
152 {
153 // prepare a context
154 CssmClient::GenerateKey generate(Server::csp(), context.algorithm());
155 generate.override(context);
156
157 // generate key
158 // @@@ turn "none" return into reference if permanent (only)
159 CssmKey key;
160 generate(key, LocalKey::KeySpec(usage, attrs));
161
162 // register and return the generated key
163 newKey = makeKey(key, attrs & LocalKey::managedAttributes, owner);
164 }
165
166 void LocalDatabase::generateKey(const Context &context,
167 const AccessCredentials *cred, const AclEntryPrototype *owner,
168 uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs,
169 RefPointer<Key> &publicKey, RefPointer<Key> &privateKey)
170 {
171 // prepare a context
172 CssmClient::GenerateKey generate(Server::csp(), context.algorithm());
173 generate.override(context);
174
175 // this may take a while; let our server object know
176 Server::active().longTermActivity();
177
178 // generate keys
179 // @@@ turn "none" return into reference if permanent (only)
180 CssmKey pubKey, privKey;
181 generate(pubKey, LocalKey::KeySpec(pubUsage, pubAttrs),
182 privKey, LocalKey::KeySpec(privUsage, privAttrs));
183
184 // register and return the generated keys
185 publicKey = makeKey(pubKey, pubAttrs & LocalKey::managedAttributes,
186 (pubAttrs & CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT) ? owner : NULL);
187 privateKey = makeKey(privKey, privAttrs & LocalKey::managedAttributes, owner);
188 }
189
190
191 //
192 // Key wrapping and unwrapping.
193 // Note that the key argument (the key in the context) is optional because of the special
194 // case of "cleartext" (null algorithm) wrapping for import/export.
195 //
196
197 void LocalDatabase::wrapKey(const Context &context, const AccessCredentials *cred,
198 Key *wrappingKey, Key &keyToBeWrapped,
199 const CssmData &descriptiveData, CssmKey &wrappedKey)
200 {
201 keyToBeWrapped.validate(context.algorithm() == CSSM_ALGID_NONE ?
202 CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR : CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED,
203 cred);
204 if (wrappingKey) {
205 context.replace(CSSM_ATTRIBUTE_KEY, myKey(*wrappingKey).cssmKey());
206 wrappingKey->validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context);
207 }
208 CssmClient::WrapKey wrap(Server::csp(), context.algorithm());
209 wrap.override(context);
210 wrap.cred(cred);
211 wrap(myKey(keyToBeWrapped), wrappedKey, &descriptiveData);
212 }
213
214 void LocalDatabase::unwrapKey(const Context &context,
215 const AccessCredentials *cred, const AclEntryPrototype *owner,
216 Key *wrappingKey, Key *publicKey, CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs,
217 const CssmKey wrappedKey, RefPointer<Key> &unwrappedKey, CssmData &descriptiveData)
218 {
219 if (wrappingKey) {
220 context.replace(CSSM_ATTRIBUTE_KEY, myKey(*wrappingKey).cssmKey());
221 wrappingKey->validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context);
222 }
223 // we are not checking access on the public key, if any
224
225 CssmClient::UnwrapKey unwrap(Server::csp(), context.algorithm());
226 unwrap.override(context);
227 unwrap.cred(cred);
228
229 // the AclEntryInput will have to live until unwrap is done
230 AclEntryInput ownerInput;
231 if (owner) {
232 ownerInput.proto() = *owner;
233 unwrap.owner(ownerInput);
234 }
235
236 CssmKey result;
237 unwrap(wrappedKey, LocalKey::KeySpec(usage, attrs), result, &descriptiveData,
238 publicKey ? &myKey(*publicKey).cssmKey() : NULL);
239 unwrappedKey = makeKey(result, attrs & LocalKey::managedAttributes, owner);
240 }
241
242
243 //
244 // Key derivation
245 //
246 void LocalDatabase::deriveKey(const Context &context, Key *key,
247 const AccessCredentials *cred, const AclEntryPrototype *owner,
248 CssmData *param, uint32 usage, uint32 attrs, RefPointer<Key> &derivedKey)
249 {
250 if (key) {
251 key->validate(CSSM_ACL_AUTHORIZATION_DERIVE, context);
252 context.replace(CSSM_ATTRIBUTE_KEY, myKey(*key).cssmKey());
253 }
254 CssmClient::DeriveKey derive(Server::csp(), context.algorithm(), CSSM_ALGID_NONE);
255 derive.override(context);
256
257 // derive key
258 // @@@ turn "none" return into reference if permanent (only)
259 CssmKey dKey;
260 derive(param, LocalKey::KeySpec(usage, attrs), dKey);
261
262 // register and return the generated key
263 derivedKey = makeKey(dKey, attrs & LocalKey::managedAttributes, owner);
264 }
265
266
267 //
268 // Miscellaneous CSSM functions
269 //
270 void LocalDatabase::getOutputSize(const Context &context, Key &key, uint32 inputSize,
271 bool encrypt, uint32 &result)
272 {
273 // We're fudging here somewhat, since the context can be any type.
274 // ctx.override will fix the type, and no-one's the wiser.
275 context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
276 CssmClient::Digest ctx(Server::csp(), context.algorithm());
277 ctx.override(context);
278 result = ctx.getOutputSize(inputSize, encrypt);
279 }