]> git.saurik.com Git - apple/security.git/blame - securityd/src/localdatabase.cpp
Security-59306.101.1.tar.gz
[apple/security.git] / securityd / src / localdatabase.cpp
CommitLineData
d8f41ccd
A
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"
d8f41ccd
A
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//
45LocalDatabase::LocalDatabase(Process &proc)
46 : Database(proc)
47{
48}
49
50
51static inline LocalKey &myKey(Key &key)
52{
53 return safer_cast<LocalKey &>(key);
54}
55
56
57//
58// Key inquiries
59//
60void 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//
70void 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
80void 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
89void 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
99void 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//
113void 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
128void 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//
149void 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
166void 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
197void 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,
dd5fb164 203 cred, &keyToBeWrapped.database());
d8f41ccd
A
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
214void 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//
246void 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//
270void 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}