#include "localdatabase.h"
#include "agentquery.h"
#include "localkey.h"
#include "server.h"
#include "session.h"
#include <security_cdsa_utilities/acl_any.h> // for default owner ACLs
#include <security_cdsa_client/wrapkey.h>
#include <security_cdsa_client/genkey.h>
#include <security_cdsa_client/signclient.h>
#include <security_cdsa_client/cryptoclient.h>
#include <security_cdsa_client/macclient.h>
#include <security_utilities/endian.h>
LocalDatabase::LocalDatabase(Process &proc)
: Database(proc)
{
}
static inline LocalKey &myKey(Key &key)
{
return safer_cast<LocalKey &>(key);
}
void LocalDatabase::queryKeySizeInBits(Key &key, CssmKeySize &result)
{
CssmClient::Key theKey(Server::csp(), myKey(key));
result = theKey.sizeInBits();
}
void LocalDatabase::generateSignature(const Context &context, Key &key,
CSSM_ALGORITHMS signOnlyAlgorithm, const CssmData &data, CssmData &signature)
{
context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
key.validate(CSSM_ACL_AUTHORIZATION_SIGN, context);
CssmClient::Sign signer(Server::csp(), context.algorithm(), signOnlyAlgorithm);
signer.override(context);
signer.sign(data, signature);
}
void LocalDatabase::verifySignature(const Context &context, Key &key,
CSSM_ALGORITHMS verifyOnlyAlgorithm, const CssmData &data, const CssmData &signature)
{
context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
CssmClient::Verify verifier(Server::csp(), context.algorithm(), verifyOnlyAlgorithm);
verifier.override(context);
verifier.verify(data, signature);
}
void LocalDatabase::generateMac(const Context &context, Key &key,
const CssmData &data, CssmData &mac)
{
context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
key.validate(CSSM_ACL_AUTHORIZATION_MAC, context);
CssmClient::GenerateMac signer(Server::csp(), context.algorithm());
signer.override(context);
signer.sign(data, mac);
}
void LocalDatabase::verifyMac(const Context &context, Key &key,
const CssmData &data, const CssmData &mac)
{
context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
key.validate(CSSM_ACL_AUTHORIZATION_MAC, context);
CssmClient::VerifyMac verifier(Server::csp(), context.algorithm());
verifier.override(context);
verifier.verify(data, mac);
}
void LocalDatabase::encrypt(const Context &context, Key &key,
const CssmData &clear, CssmData &cipher)
{
context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
key.validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context);
CssmClient::Encrypt cryptor(Server::csp(), context.algorithm());
cryptor.override(context);
CssmData remData;
size_t totalLength = cryptor.encrypt(clear, cipher, remData);
if (remData)
CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
cipher.length(totalLength);
}
void LocalDatabase::decrypt(const Context &context, Key &key,
const CssmData &cipher, CssmData &clear)
{
context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
key.validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context);
CssmClient::Decrypt cryptor(Server::csp(), context.algorithm());
cryptor.override(context);
CssmData remData;
size_t totalLength = cryptor.decrypt(cipher, clear, remData);
if (remData)
CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
clear.length(totalLength);
}
void LocalDatabase::generateKey(const Context &context,
const AccessCredentials *cred, const AclEntryPrototype *owner,
uint32 usage, uint32 attrs, RefPointer<Key> &newKey)
{
CssmClient::GenerateKey generate(Server::csp(), context.algorithm());
generate.override(context);
CssmKey key;
generate(key, LocalKey::KeySpec(usage, attrs));
newKey = makeKey(key, attrs & LocalKey::managedAttributes, owner);
}
void LocalDatabase::generateKey(const Context &context,
const AccessCredentials *cred, const AclEntryPrototype *owner,
uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs,
RefPointer<Key> &publicKey, RefPointer<Key> &privateKey)
{
CssmClient::GenerateKey generate(Server::csp(), context.algorithm());
generate.override(context);
Server::active().longTermActivity();
CssmKey pubKey, privKey;
generate(pubKey, LocalKey::KeySpec(pubUsage, pubAttrs),
privKey, LocalKey::KeySpec(privUsage, privAttrs));
publicKey = makeKey(pubKey, pubAttrs & LocalKey::managedAttributes,
(pubAttrs & CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT) ? owner : NULL);
privateKey = makeKey(privKey, privAttrs & LocalKey::managedAttributes, owner);
}
void LocalDatabase::wrapKey(const Context &context, const AccessCredentials *cred,
Key *wrappingKey, Key &keyToBeWrapped,
const CssmData &descriptiveData, CssmKey &wrappedKey)
{
keyToBeWrapped.validate(context.algorithm() == CSSM_ALGID_NONE ?
CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR : CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED,
cred, &keyToBeWrapped.database());
if (wrappingKey) {
context.replace(CSSM_ATTRIBUTE_KEY, myKey(*wrappingKey).cssmKey());
wrappingKey->validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context);
}
CssmClient::WrapKey wrap(Server::csp(), context.algorithm());
wrap.override(context);
wrap.cred(cred);
wrap(myKey(keyToBeWrapped), wrappedKey, &descriptiveData);
}
void LocalDatabase::unwrapKey(const Context &context,
const AccessCredentials *cred, const AclEntryPrototype *owner,
Key *wrappingKey, Key *publicKey, CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs,
const CssmKey wrappedKey, RefPointer<Key> &unwrappedKey, CssmData &descriptiveData)
{
if (wrappingKey) {
context.replace(CSSM_ATTRIBUTE_KEY, myKey(*wrappingKey).cssmKey());
wrappingKey->validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context);
}
CssmClient::UnwrapKey unwrap(Server::csp(), context.algorithm());
unwrap.override(context);
unwrap.cred(cred);
AclEntryInput ownerInput;
if (owner) {
ownerInput.proto() = *owner;
unwrap.owner(ownerInput);
}
CssmKey result;
unwrap(wrappedKey, LocalKey::KeySpec(usage, attrs), result, &descriptiveData,
publicKey ? &myKey(*publicKey).cssmKey() : NULL);
unwrappedKey = makeKey(result, attrs & LocalKey::managedAttributes, owner);
}
void LocalDatabase::deriveKey(const Context &context, Key *key,
const AccessCredentials *cred, const AclEntryPrototype *owner,
CssmData *param, uint32 usage, uint32 attrs, RefPointer<Key> &derivedKey)
{
if (key) {
key->validate(CSSM_ACL_AUTHORIZATION_DERIVE, context);
context.replace(CSSM_ATTRIBUTE_KEY, myKey(*key).cssmKey());
}
CssmClient::DeriveKey derive(Server::csp(), context.algorithm(), CSSM_ALGID_NONE);
derive.override(context);
CssmKey dKey;
derive(param, LocalKey::KeySpec(usage, attrs), dKey);
derivedKey = makeKey(dKey, attrs & LocalKey::managedAttributes, owner);
}
void LocalDatabase::getOutputSize(const Context &context, Key &key, uint32 inputSize,
bool encrypt, uint32 &result)
{
context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey());
CssmClient::Digest ctx(Server::csp(), context.algorithm());
ctx.override(context);
result = ctx.getOutputSize(inputSize, encrypt);
}