#include "SDKey.h"
#include "SDCSPSession.h"
#include "SDCSPDLSession.h"
#include "SDDLSession.h"
#include <security_cdsa_utilities/KeySchema.h>
#include <security_cdsa_utilities/cssmdb.h>
#include <security_cdsa_plugin/cssmplugin.h>
using namespace CssmClient;
using namespace SecurityServer;
SDKey::SDKey(SDCSPSession &session, KeyHandle hKey, CssmKey &ioKey,
CSSM_DB_HANDLE inDBHandle, uint32 inKeyAttr,
const CssmData *inKeyLabel)
: ReferencedKey(session.mSDCSPDLSession),
mAllocator(session), mKeyHandle(hKey),
mClientSession(session.clientSession())
{
CssmKey::Header &header = ioKey.header();
#if 0
if (inKeyAttr & CSSM_KEYATTR_PERMANENT)
{
if (!inDBHandle)
CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE);
CssmDataContainer blob(mAllocator);
clientSession().encodeKey(keyHandle, blob);
assert(header.HeaderVersion == CSSM_KEYHEADER_VERSION);
switch (header.KeyClass)
{
case CSSM_KEYCLASS_PUBLIC_KEY:
mRecordType = CSSM_DL_DB_RECORD_PUBLIC_KEY;
break;
case CSSM_KEYCLASS_PRIVATE_KEY:
mRecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY;
break;
case CSSM_KEYCLASS_SESSION_KEY:
mRecordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY;
break;
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
}
CssmData label;
if (inKeyLabel)
label = *inKeyLabel;
CssmData none;
CssmGuidData creatorGuid(header.CspId);
CssmDateData startDate(header.StartDate);
CssmDateData endDate(header.EndDate);
DbAttributes attributes(inDBHandle);
attributes.recordType(mRecordType);
attributes.add(KeySchema::KeyClass, mRecordType);
attributes.add(KeySchema::PrintName, label);
attributes.add(KeySchema::Alias, none);
attributes.add(KeySchema::Permanent,
header.attribute(CSSM_KEYATTR_PERMANENT));
attributes.add(KeySchema::Private,
header.attribute(CSSM_KEYATTR_PRIVATE));
attributes.add(KeySchema::Modifiable,
header.attribute(CSSM_KEYATTR_MODIFIABLE));
attributes.add(KeySchema::Label, label);
attributes.add(KeySchema::ApplicationTag, none);
attributes.add(KeySchema::KeyCreator, creatorGuid);
attributes.add(KeySchema::KeyType, header.AlgorithmId);
attributes.add(KeySchema::KeySizeInBits, header.LogicalKeySizeInBits);
attributes.add(KeySchema::EffectiveKeySize, header.LogicalKeySizeInBits);
attributes.add(KeySchema::StartDate, startDate);
attributes.add(KeySchema::EndDate, endDate);
attributes.add(KeySchema::Sensitive,
header.attribute(CSSM_KEYATTR_SENSITIVE));
attributes.add(KeySchema::AlwaysSensitive,
header.attribute(CSSM_KEYATTR_ALWAYS_SENSITIVE));
attributes.add(KeySchema::Extractable,
header.attribute(CSSM_KEYATTR_EXTRACTABLE));
attributes.add(KeySchema::NeverExtractable,
header.attribute(CSSM_KEYATTR_NEVER_EXTRACTABLE));
attributes.add(KeySchema::Encrypt,
header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_ENCRYPT));
attributes.add(KeySchema::Decrypt,
header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_DECRYPT));
attributes.add(KeySchema::Derive,
header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_DERIVE));
attributes.add(KeySchema::Sign,
header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_SIGN));
attributes.add(KeySchema::Verify,
header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_VERIFY));
attributes.add(KeySchema::SignRecover,
header.useFor(CSSM_KEYUSE_ANY
| CSSM_KEYUSE_SIGN_RECOVER));
attributes.add(KeySchema::VerifyRecover,
header.useFor(CSSM_KEYUSE_ANY
| CSSM_KEYUSE_VERIFY_RECOVER));
attributes.add(KeySchema::Wrap,
header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_WRAP));
attributes.add(KeySchema::Unwrap,
header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_UNWRAP));
mUniqueId = inDBHandle->insert(mRecordType, &attributes, &blob,
true);
}
#endif
header.cspGuid(session.plugin.myGuid()); makeReferenceKey(mAllocator, keyReference(), ioKey);
}
SDKey::SDKey(SDDLSession &session, CssmKey &ioKey, KeyHandle hKey, CSSM_DB_HANDLE inDBHandle,
RecordHandle record, CSSM_DB_RECORDTYPE recordType,
CssmData &keyBlob)
: ReferencedKey(session.mSDCSPDLSession),
mAllocator(session.allocator()), mKeyHandle(hKey), mRecord(record),
mClientSession(session.clientSession())
{
CssmKey::Header &header = ioKey.header();
#if 0
memset(&header, 0, sizeof(header));
if (!mUniqueId || !mUniqueId->database())
CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
header.HeaderVersion = CSSM_KEYHEADER_VERSION;
switch (mRecordType)
{
case CSSM_DL_DB_RECORD_PUBLIC_KEY:
header.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
break;
case CSSM_DL_DB_RECORD_PRIVATE_KEY:
header.KeyClass = CSSM_KEYCLASS_PRIVATE_KEY;
break;
case CSSM_DL_DB_RECORD_SYMMETRIC_KEY:
header.KeyClass = CSSM_KEYCLASS_SESSION_KEY;
break;
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
}
DbAttributes attributes(mUniqueId->database());
attributes.recordType(mRecordType);
attributes.add(KeySchema::KeyClass); attributes.add(KeySchema::Permanent); attributes.add(KeySchema::Private); attributes.add(KeySchema::Modifiable); attributes.add(KeySchema::KeyCreator); attributes.add(KeySchema::KeyType); attributes.add(KeySchema::KeySizeInBits); attributes.add(KeySchema::StartDate); attributes.add(KeySchema::EndDate); attributes.add(KeySchema::Sensitive); attributes.add(KeySchema::AlwaysSensitive); attributes.add(KeySchema::Extractable); attributes.add(KeySchema::NeverExtractable); attributes.add(KeySchema::Encrypt); attributes.add(KeySchema::Decrypt); attributes.add(KeySchema::Derive); attributes.add(KeySchema::Sign); attributes.add(KeySchema::Verify); attributes.add(KeySchema::SignRecover); attributes.add(KeySchema::VerifyRecover); attributes.add(KeySchema::Wrap); attributes.add(KeySchema::Unwrap);
mUniqueId->get(&attributes, NULL);
if (mRecordType != uint32(attributes[0]))
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
header.AlgorithmId = attributes[5]; header.LogicalKeySizeInBits = attributes[6];
if (attributes[1]) header.setAttribute(CSSM_KEYATTR_PERMANENT);
if (attributes[2]) header.setAttribute(CSSM_KEYATTR_PRIVATE);
if (attributes[3]) header.setAttribute(CSSM_KEYATTR_MODIFIABLE);
if (attributes[9]) header.setAttribute(CSSM_KEYATTR_SENSITIVE);
if (attributes[11]) header.setAttribute(CSSM_KEYATTR_EXTRACTABLE);
if (attributes[10]) header.setAttribute(CSSM_KEYATTR_ALWAYS_SENSITIVE);
if (attributes[12]) header.setAttribute(CSSM_KEYATTR_NEVER_EXTRACTABLE);
if (attributes[13]) header.usage(CSSM_KEYUSE_ENCRYPT);
if (attributes[14]) header.usage(CSSM_KEYUSE_DECRYPT);
if (attributes[15]) header.usage(CSSM_KEYUSE_DERIVE);
if (attributes[16]) header.usage(CSSM_KEYUSE_SIGN);
if (attributes[17]) header.usage(CSSM_KEYUSE_VERIFY);
if (attributes[18]) header.usage(CSSM_KEYUSE_SIGN_RECOVER);
if (attributes[19]) header.usage(CSSM_KEYUSE_VERIFY_RECOVER);
if (attributes[20]) header.usage(CSSM_KEYUSE_WRAP);
if (attributes[21]) header.usage(CSSM_KEYUSE_UNWRAP);
if (header.usage() == (CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT
| CSSM_KEYUSE_DERIVE | CSSM_KEYUSE_SIGN
| CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_SIGN_RECOVER
| CSSM_KEYUSE_VERIFY_RECOVER | CSSM_KEYUSE_WRAP
| CSSM_KEYUSE_UNWRAP))
header.usage(CSSM_KEYUSE_ANY);
if (!attributes[7].size() || !attributes[8].size())
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
header.StartDate = attributes[7].at<CSSM_DATE>(0);
header.EndDate = attributes[8].at<CSSM_DATE>(0);
#endif
makeReferenceKey(mAllocator, keyReference(), ioKey);
header.cspGuid(session.plugin.myGuid()); }
SDKey::~SDKey()
{
if (mKeyHandle != noKey)
clientSession().releaseKey(mKeyHandle);
}
void
SDKey::free(const AccessCredentials *accessCred, CssmKey &ioKey,
CSSM_BOOL deleteKey)
{
freeReferenceKey(mAllocator, ioKey);
if (deleteKey)
{
if (!mRecord || !mDatabase)
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
clientSession().deleteRecord(ClientSession::toIPCHandle(mDatabase), ClientSession::toIPCHandle(mRecord));
}
if (mKeyHandle != noKey)
{
clientSession().releaseKey(mKeyHandle);
mKeyHandle = noKey;
}
}
SecurityServer::ClientSession &
SDKey::clientSession()
{
return mClientSession;
}
KeyHandle SDKey::optionalKeyHandle() const
{
return mKeyHandle;
}
KeyHandle
SDKey::keyHandle()
{
if (mKeyHandle == noKey)
{
#if 0
if (!mUniqueId || !mUniqueId->database())
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
CssmDataContainer blob(mAllocator);
mUniqueId->get(NULL, &blob);
CssmKey::Header dummyHeader; mKeyHandle =
clientSession().decodeKey(mUniqueId->database().dbHandle(), blob,
dummyHeader);
#else
abort();
#endif
}
return mKeyHandle;
}
void
SDKey::getOwner(CSSM_ACL_OWNER_PROTOTYPE &owner, Allocator &allocator)
{
clientSession().getKeyOwner(keyHandle(), AclOwnerPrototype::overlay(owner),
allocator);
}
void
SDKey::changeOwner(const AccessCredentials &accessCred,
const AclOwnerPrototype &newOwner)
{
clientSession().changeKeyOwner(keyHandle(), accessCred, newOwner);
}
void
SDKey::getAcl(const char *selectionTag, uint32 &numberOfAclInfos,
AclEntryInfo *&aclInfos, Allocator &allocator)
{
clientSession().getKeyAcl(keyHandle(), selectionTag, numberOfAclInfos,
aclInfos, allocator);
}
void
SDKey::changeAcl(const AccessCredentials &accessCred, const AclEdit &aclEdit)
{
clientSession().changeKeyAcl(keyHandle(), accessCred, aclEdit);
}