#include <security_cdsa_utilities/cssmdata.h>
#include <security_cdsa_utilities/cssmkey.h>
#include <security_cdsa_client/wrapkey.h>
#include "tempdatabase.h"
#include "localkey.h"
#include "server.h"
#include "session.h"
#include "agentquery.h"
class TempKey : public LocalKey, public SecurityServerAcl {
public:
TempKey(Database &db, const CssmKey &newKey, uint32 moreAttributes,
const AclEntryPrototype *owner = NULL);
Database *relatedDatabase();
SecurityServerAcl &acl() { return *this; }
public:
AclKind aclKind() const;
};
TempKey::TempKey(Database &db, const CssmKey &newKey, uint32 moreAttributes,
const AclEntryPrototype *owner)
: LocalKey(db, newKey, moreAttributes)
{
setOwner(owner);
db.addReference(*this);
}
AclKind TempKey::aclKind() const
{
return keyAcl;
}
Database *TempKey::relatedDatabase()
{
return NULL;
}
TempDatabase::TempDatabase(Process &proc)
: LocalDatabase(proc)
{
proc.addReference(*this);
}
const char *TempDatabase::dbName() const
{
return "(transient)";
}
uint32 TempDatabase::dbVersion() {
return CommonBlob::version_MacOS_10_0;
}
bool TempDatabase::transient() const
{
return true;
}
void TempDatabase::getSecurePassphrase(const Context &context,
string &passphrase)
{
uint32 verify = context.getInt(CSSM_ATTRIBUTE_VERIFY_PASSPHRASE, CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT);
CssmData *promptData = context.get<CssmData>(CSSM_ATTRIBUTE_PROMPT);
QueryGenericPassphrase agentQuery;
agentQuery.inferHints(Server::process());
agentQuery(promptData, verify, passphrase);
}
void TempDatabase::makeSecurePassphraseKey(const Context &context,
const AccessCredentials *cred,
const AclEntryPrototype *owner,
uint32 usage, uint32 attrs,
RefPointer<Key> &newKey)
{
secdebug("SSdb", "requesting secure passphrase");
string passphrase;
getSecurePassphrase(context, passphrase);
secdebug("SSdb", "wrapping securely-obtained passphrase as key");
StringData passphraseData(passphrase);
CssmKey rawKey(passphraseData);
rawKey.algorithm(context.algorithm());
rawKey.blobType(CSSM_KEYBLOB_RAW);
rawKey.blobFormat(CSSM_KEYBLOB_WRAPPED_FORMAT_NONE);
rawKey.keyClass(CSSM_KEYCLASS_SESSION_KEY);
CssmClient::UnwrapKey unwrap(Server::csp(), CSSM_ALGID_NONE);
CssmKey cspKey;
unwrap(rawKey, TempKey::KeySpec(usage, attrs), cspKey);
newKey = makeKey(cspKey, attrs & TempKey::managedAttributes, owner);
}
void TempDatabase::generateKey(const Context &context,
const AccessCredentials *cred,
const AclEntryPrototype *owner,
uint32 usage, uint32 attrs,
RefPointer<Key> &newKey)
{
switch (context.algorithm())
{
case CSSM_ALGID_SECURE_PASSPHRASE:
makeSecurePassphraseKey(context, cred, owner, usage, attrs, newKey);
break;
default:
LocalDatabase::generateKey(context, cred, owner, usage, attrs, newKey);
return;
}
}
RefPointer<Key> TempDatabase::makeKey(const CssmKey &newKey,
uint32 moreAttributes, const AclEntryPrototype *owner)
{
assert(!newKey.attribute(CSSM_KEYATTR_PERMANENT));
return new TempKey(*this, newKey, moreAttributes, owner);
}