2 * Copyright (c) 2004 Apple Computer, 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 // localdatabase - locally implemented database using internal CSP cryptography
28 #include "localdatabase.h"
29 #include "agentquery.h"
33 #include <security_agent_client/agentclient.h>
34 #include <security_cdsa_utilities/acl_any.h> // for default owner ACLs
35 #include <security_cdsa_client/wrapkey.h>
36 #include <security_cdsa_client/genkey.h>
37 #include <security_cdsa_client/signclient.h>
38 #include <security_cdsa_client/cryptoclient.h>
39 #include <security_cdsa_client/macclient.h>
40 #include <security_utilities/endian.h>
44 // Create a Database object from initial parameters (create operation)
46 LocalDatabase::LocalDatabase(Process
&proc
)
52 static inline LocalKey
&myKey(Key
&key
)
54 return safer_cast
<LocalKey
&>(key
);
61 void LocalDatabase::queryKeySizeInBits(Key
&key
, CssmKeySize
&result
)
63 CssmClient::Key
theKey(Server::csp(), myKey(key
));
64 result
= theKey
.sizeInBits();
69 // Signatures and MACs
71 void LocalDatabase::generateSignature(const Context
&context
, Key
&key
,
72 CSSM_ALGORITHMS signOnlyAlgorithm
, const CssmData
&data
, CssmData
&signature
)
74 context
.replace(CSSM_ATTRIBUTE_KEY
, myKey(key
).cssmKey());
75 key
.validate(CSSM_ACL_AUTHORIZATION_SIGN
, context
);
76 CssmClient::Sign
signer(Server::csp(), context
.algorithm(), signOnlyAlgorithm
);
77 signer
.override(context
);
78 signer
.sign(data
, signature
);
81 void LocalDatabase::verifySignature(const Context
&context
, Key
&key
,
82 CSSM_ALGORITHMS verifyOnlyAlgorithm
, const CssmData
&data
, const CssmData
&signature
)
84 context
.replace(CSSM_ATTRIBUTE_KEY
, myKey(key
).cssmKey());
85 CssmClient::Verify
verifier(Server::csp(), context
.algorithm(), verifyOnlyAlgorithm
);
86 verifier
.override(context
);
87 verifier
.verify(data
, signature
);
90 void LocalDatabase::generateMac(const Context
&context
, Key
&key
,
91 const CssmData
&data
, CssmData
&mac
)
93 context
.replace(CSSM_ATTRIBUTE_KEY
, myKey(key
).cssmKey());
94 key
.validate(CSSM_ACL_AUTHORIZATION_MAC
, context
);
95 CssmClient::GenerateMac
signer(Server::csp(), context
.algorithm());
96 signer
.override(context
);
97 signer
.sign(data
, mac
);
100 void LocalDatabase::verifyMac(const Context
&context
, Key
&key
,
101 const CssmData
&data
, const CssmData
&mac
)
103 context
.replace(CSSM_ATTRIBUTE_KEY
, myKey(key
).cssmKey());
104 key
.validate(CSSM_ACL_AUTHORIZATION_MAC
, context
);
105 CssmClient::VerifyMac
verifier(Server::csp(), context
.algorithm());
106 verifier
.override(context
);
107 verifier
.verify(data
, mac
);
112 // Encryption/decryption
114 void LocalDatabase::encrypt(const Context
&context
, Key
&key
,
115 const CssmData
&clear
, CssmData
&cipher
)
117 context
.replace(CSSM_ATTRIBUTE_KEY
, myKey(key
).cssmKey());
118 key
.validate(CSSM_ACL_AUTHORIZATION_ENCRYPT
, context
);
119 CssmClient::Encrypt
cryptor(Server::csp(), context
.algorithm());
120 cryptor
.override(context
);
122 size_t totalLength
= cryptor
.encrypt(clear
, cipher
, remData
);
123 // shouldn't need remData - if an algorithm REQUIRES this, we'd have to ship it
125 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
126 cipher
.length(totalLength
);
129 void LocalDatabase::decrypt(const Context
&context
, Key
&key
,
130 const CssmData
&cipher
, CssmData
&clear
)
132 context
.replace(CSSM_ATTRIBUTE_KEY
, myKey(key
).cssmKey());
133 key
.validate(CSSM_ACL_AUTHORIZATION_DECRYPT
, context
);
134 CssmClient::Decrypt
cryptor(Server::csp(), context
.algorithm());
135 cryptor
.override(context
);
137 size_t totalLength
= cryptor
.decrypt(cipher
, clear
, remData
);
138 // shouldn't need remData - if an algorithm REQUIRES this, we'd have to ship it
140 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
141 clear
.length(totalLength
);
146 // Key generation and derivation.
147 // Currently, we consider symmetric key generation to be fast, but
148 // asymmetric key generation to be (potentially) slow.
150 void LocalDatabase::generateKey(const Context
&context
,
151 const AccessCredentials
*cred
, const AclEntryPrototype
*owner
,
152 uint32 usage
, uint32 attrs
, RefPointer
<Key
> &newKey
)
155 CssmClient::GenerateKey
generate(Server::csp(), context
.algorithm());
156 generate
.override(context
);
159 // @@@ turn "none" return into reference if permanent (only)
161 generate(key
, LocalKey::KeySpec(usage
, attrs
));
163 // register and return the generated key
164 newKey
= makeKey(key
, attrs
& LocalKey::managedAttributes
, owner
);
167 void LocalDatabase::generateKey(const Context
&context
,
168 const AccessCredentials
*cred
, const AclEntryPrototype
*owner
,
169 uint32 pubUsage
, uint32 pubAttrs
, uint32 privUsage
, uint32 privAttrs
,
170 RefPointer
<Key
> &publicKey
, RefPointer
<Key
> &privateKey
)
173 CssmClient::GenerateKey
generate(Server::csp(), context
.algorithm());
174 generate
.override(context
);
176 // this may take a while; let our server object know
177 Server::active().longTermActivity();
180 // @@@ turn "none" return into reference if permanent (only)
181 CssmKey pubKey
, privKey
;
182 generate(pubKey
, LocalKey::KeySpec(pubUsage
, pubAttrs
),
183 privKey
, LocalKey::KeySpec(privUsage
, privAttrs
));
185 // register and return the generated keys
186 publicKey
= makeKey(pubKey
, pubAttrs
& LocalKey::managedAttributes
,
187 (pubAttrs
& CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT
) ? owner
: NULL
);
188 privateKey
= makeKey(privKey
, privAttrs
& LocalKey::managedAttributes
, owner
);
193 // Key wrapping and unwrapping.
194 // Note that the key argument (the key in the context) is optional because of the special
195 // case of "cleartext" (null algorithm) wrapping for import/export.
198 void LocalDatabase::wrapKey(const Context
&context
, const AccessCredentials
*cred
,
199 Key
*wrappingKey
, Key
&keyToBeWrapped
,
200 const CssmData
&descriptiveData
, CssmKey
&wrappedKey
)
202 keyToBeWrapped
.validate(context
.algorithm() == CSSM_ALGID_NONE
?
203 CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR
: CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
,
206 context
.replace(CSSM_ATTRIBUTE_KEY
, myKey(*wrappingKey
).cssmKey());
207 wrappingKey
->validate(CSSM_ACL_AUTHORIZATION_ENCRYPT
, context
);
209 CssmClient::WrapKey
wrap(Server::csp(), context
.algorithm());
210 wrap
.override(context
);
212 wrap(myKey(keyToBeWrapped
), wrappedKey
, &descriptiveData
);
215 void LocalDatabase::unwrapKey(const Context
&context
,
216 const AccessCredentials
*cred
, const AclEntryPrototype
*owner
,
217 Key
*wrappingKey
, Key
*publicKey
, CSSM_KEYUSE usage
, CSSM_KEYATTR_FLAGS attrs
,
218 const CssmKey wrappedKey
, RefPointer
<Key
> &unwrappedKey
, CssmData
&descriptiveData
)
221 context
.replace(CSSM_ATTRIBUTE_KEY
, myKey(*wrappingKey
).cssmKey());
222 wrappingKey
->validate(CSSM_ACL_AUTHORIZATION_DECRYPT
, context
);
224 // we are not checking access on the public key, if any
226 CssmClient::UnwrapKey
unwrap(Server::csp(), context
.algorithm());
227 unwrap
.override(context
);
230 // the AclEntryInput will have to live until unwrap is done
231 AclEntryInput ownerInput
;
233 ownerInput
.proto() = *owner
;
234 unwrap
.owner(ownerInput
);
238 unwrap(wrappedKey
, LocalKey::KeySpec(usage
, attrs
), result
, &descriptiveData
,
239 publicKey
? &myKey(*publicKey
).cssmKey() : NULL
);
240 unwrappedKey
= makeKey(result
, attrs
& LocalKey::managedAttributes
, owner
);
247 void LocalDatabase::deriveKey(const Context
&context
, Key
*key
,
248 const AccessCredentials
*cred
, const AclEntryPrototype
*owner
,
249 CssmData
*param
, uint32 usage
, uint32 attrs
, RefPointer
<Key
> &derivedKey
)
252 key
->validate(CSSM_ACL_AUTHORIZATION_DERIVE
, cred
);
253 context
.replace(CSSM_ATTRIBUTE_KEY
, myKey(*key
).cssmKey());
255 CssmClient::DeriveKey
derive(Server::csp(), context
.algorithm(), CSSM_ALGID_NONE
);
256 derive
.override(context
);
259 // @@@ turn "none" return into reference if permanent (only)
261 derive(param
, LocalKey::KeySpec(usage
, attrs
), dKey
);
263 // register and return the generated key
264 derivedKey
= makeKey(dKey
, attrs
& LocalKey::managedAttributes
, owner
);
269 // Miscellaneous CSSM functions
271 void LocalDatabase::getOutputSize(const Context
&context
, Key
&key
, uint32 inputSize
,
272 bool encrypt
, uint32
&result
)
274 // We're fudging here somewhat, since the context can be any type.
275 // ctx.override will fix the type, and no-one's the wiser.
276 context
.replace(CSSM_ATTRIBUTE_KEY
, myKey(key
).cssmKey());
277 CssmClient::Digest
ctx(Server::csp(), context
.algorithm());
278 ctx
.override(context
);
279 result
= ctx
.getOutputSize(inputSize
, encrypt
);