2 * Copyright (c) 2004,2006,2008 Apple 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_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>
43 // Create a Database object from initial parameters (create operation)
45 LocalDatabase::LocalDatabase(Process
&proc
)
51 static inline LocalKey
&myKey(Key
&key
)
53 return safer_cast
<LocalKey
&>(key
);
60 void LocalDatabase::queryKeySizeInBits(Key
&key
, CssmKeySize
&result
)
62 CssmClient::Key
theKey(Server::csp(), myKey(key
));
63 result
= theKey
.sizeInBits();
68 // Signatures and MACs
70 void LocalDatabase::generateSignature(const Context
&context
, Key
&key
,
71 CSSM_ALGORITHMS signOnlyAlgorithm
, const CssmData
&data
, CssmData
&signature
)
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
);
80 void LocalDatabase::verifySignature(const Context
&context
, Key
&key
,
81 CSSM_ALGORITHMS verifyOnlyAlgorithm
, const CssmData
&data
, const CssmData
&signature
)
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
);
89 void LocalDatabase::generateMac(const Context
&context
, Key
&key
,
90 const CssmData
&data
, CssmData
&mac
)
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
);
99 void LocalDatabase::verifyMac(const Context
&context
, Key
&key
,
100 const CssmData
&data
, const CssmData
&mac
)
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
);
111 // Encryption/decryption
113 void LocalDatabase::encrypt(const Context
&context
, Key
&key
,
114 const CssmData
&clear
, CssmData
&cipher
)
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
);
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
124 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
125 cipher
.length(totalLength
);
128 void LocalDatabase::decrypt(const Context
&context
, Key
&key
,
129 const CssmData
&cipher
, CssmData
&clear
)
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
);
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
139 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
140 clear
.length(totalLength
);
145 // Key generation and derivation.
146 // Currently, we consider symmetric key generation to be fast, but
147 // asymmetric key generation to be (potentially) slow.
149 void LocalDatabase::generateKey(const Context
&context
,
150 const AccessCredentials
*cred
, const AclEntryPrototype
*owner
,
151 uint32 usage
, uint32 attrs
, RefPointer
<Key
> &newKey
)
154 CssmClient::GenerateKey
generate(Server::csp(), context
.algorithm());
155 generate
.override(context
);
158 // @@@ turn "none" return into reference if permanent (only)
160 generate(key
, LocalKey::KeySpec(usage
, attrs
));
162 // register and return the generated key
163 newKey
= makeKey(key
, attrs
& LocalKey::managedAttributes
, owner
);
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
)
172 CssmClient::GenerateKey
generate(Server::csp(), context
.algorithm());
173 generate
.override(context
);
175 // this may take a while; let our server object know
176 Server::active().longTermActivity();
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
));
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
);
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.
197 void LocalDatabase::wrapKey(const Context
&context
, const AccessCredentials
*cred
,
198 Key
*wrappingKey
, Key
&keyToBeWrapped
,
199 const CssmData
&descriptiveData
, CssmKey
&wrappedKey
)
201 keyToBeWrapped
.validate(context
.algorithm() == CSSM_ALGID_NONE
?
202 CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR
: CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
,
203 cred
, &keyToBeWrapped
.database());
205 context
.replace(CSSM_ATTRIBUTE_KEY
, myKey(*wrappingKey
).cssmKey());
206 wrappingKey
->validate(CSSM_ACL_AUTHORIZATION_ENCRYPT
, context
);
208 CssmClient::WrapKey
wrap(Server::csp(), context
.algorithm());
209 wrap
.override(context
);
211 wrap(myKey(keyToBeWrapped
), wrappedKey
, &descriptiveData
);
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
)
220 context
.replace(CSSM_ATTRIBUTE_KEY
, myKey(*wrappingKey
).cssmKey());
221 wrappingKey
->validate(CSSM_ACL_AUTHORIZATION_DECRYPT
, context
);
223 // we are not checking access on the public key, if any
225 CssmClient::UnwrapKey
unwrap(Server::csp(), context
.algorithm());
226 unwrap
.override(context
);
229 // the AclEntryInput will have to live until unwrap is done
230 AclEntryInput ownerInput
;
232 ownerInput
.proto() = *owner
;
233 unwrap
.owner(ownerInput
);
237 unwrap(wrappedKey
, LocalKey::KeySpec(usage
, attrs
), result
, &descriptiveData
,
238 publicKey
? &myKey(*publicKey
).cssmKey() : NULL
);
239 unwrappedKey
= makeKey(result
, attrs
& LocalKey::managedAttributes
, owner
);
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
)
251 key
->validate(CSSM_ACL_AUTHORIZATION_DERIVE
, context
);
252 context
.replace(CSSM_ATTRIBUTE_KEY
, myKey(*key
).cssmKey());
254 CssmClient::DeriveKey
derive(Server::csp(), context
.algorithm(), CSSM_ALGID_NONE
);
255 derive
.override(context
);
258 // @@@ turn "none" return into reference if permanent (only)
260 derive(param
, LocalKey::KeySpec(usage
, attrs
), dKey
);
262 // register and return the generated key
263 derivedKey
= makeKey(dKey
, attrs
& LocalKey::managedAttributes
, owner
);
268 // Miscellaneous CSSM functions
270 void LocalDatabase::getOutputSize(const Context
&context
, Key
&key
, uint32 inputSize
,
271 bool encrypt
, uint32
&result
)
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
);