#include "localkey.h"
#include "server.h"
#include "database.h"
#include <security_cdsa_utilities/acl_any.h>
LocalKey::LocalKey(Database &db, const CssmKey &newKey, CSSM_KEYATTR_FLAGS moreAttributes)
: Key(db), mDigest(Server::csp().allocator())
{
mValidKey = true;
setup(newKey, moreAttributes);
secdebug("SSkey", "%p (handle %#x) created from key alg=%u use=0x%x attr=0x%x db=%p",
this, handle(), mKey.header().algorithm(), mKey.header().usage(), mAttributes, &db);
}
LocalKey::LocalKey(Database &db, CSSM_KEYATTR_FLAGS attributes)
: Key(db), mValidKey(false), mAttributes(attributes), mDigest(Server::csp().allocator())
{
}
void LocalKey::setup(const CssmKey &newKey, CSSM_KEYATTR_FLAGS moreAttributes)
{
mKey = CssmClient::Key(Server::csp(), newKey, false);
CssmKey::Header &header = mKey->header();
header = newKey.header();
mAttributes = (header.attributes() & ~forcedAttributes) | moreAttributes;
if (!(mAttributes & CSSM_KEYATTR_EXTRACTABLE))
mAttributes |= CSSM_KEYATTR_NEVER_EXTRACTABLE;
if (mAttributes & CSSM_KEYATTR_SENSITIVE)
mAttributes |= CSSM_KEYATTR_ALWAYS_SENSITIVE;
assert((header.attributes() & managedAttributes) == forcedAttributes);
}
LocalKey::~LocalKey()
{
secdebug("SSkey", "%p destroyed", this);
}
void LocalKey::setOwner(const AclEntryPrototype *owner)
{
if (owner && !owner->subject().empty())
acl().cssmSetInitial(*owner); else
acl().cssmSetInitial(new AnyAclSubject()); }
LocalDatabase &LocalKey::database() const
{
return referent<LocalDatabase>();
}
CssmClient::Key LocalKey::keyValue()
{
StLock<Mutex> _(*this);
if (!mValidKey) {
getKey();
mValidKey = true;
}
return mKey;
}
CSSM_KEYATTR_FLAGS LocalKey::attributes()
{
return mAttributes;
}
void LocalKey::returnKey(U32HandleObject::Handle &h, CssmKey::Header &hdr)
{
StLock<Mutex> _(*this);
h = this->handle();
if (mValidKey) {
hdr = mKey.header();
} else {
getHeader(hdr);
}
hdr.clearAttribute(forcedAttributes);
hdr.setAttribute(mAttributes);
}
const CssmData &LocalKey::canonicalDigest()
{
StLock<Mutex> _(*this);
if (!mDigest) {
CssmClient::PassThrough ctx(Server::csp());
ctx.key(keyValue());
CssmData *digest = NULL;
ctx(CSSM_APPLECSP_KEYDIGEST, (const void *)NULL, &digest);
assert(digest);
mDigest.set(*digest); Server::csp().allocator().free(digest); }
return mDigest.get();
}
void LocalKey::getKey()
{
assert(false);
}
void LocalKey::getHeader(CssmKey::Header &)
{
assert(false);
}
LocalKey::KeySpec::KeySpec(CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs)
: CssmClient::KeySpec(usage, (attrs & ~managedAttributes) | forcedAttributes)
{
if (attrs & generatedAttributes)
CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
}
LocalKey::KeySpec::KeySpec(CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, const CssmData &label)
: CssmClient::KeySpec(usage, (attrs & ~managedAttributes) | forcedAttributes, label)
{
if (attrs & generatedAttributes)
CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
}