+++ /dev/null
-/*
- * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
- *
- * The contents of this file constitute Original Code as defined in and are
- * subject to the Apple Public Source License Version 1.2 (the 'License').
- * You may not use this file except in compliance with the License. Please obtain
- * a copy of the License at http://www.apple.com/publicsource and read it before
- * using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
- * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
- * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
- * specific language governing rights and limitations under the License.
- */
-
-
-//
-// key - representation of SecurityServer key objects
-//
-#include "key.h"
-#include "server.h"
-#include "xdatabase.h"
-#include <Security/acl_any.h>
-
-
-//
-// Create a Key object from a database-encoded blob.
-// Note that this doesn't decode the blob (yet).
-//
-Key::Key(Database &db, const KeyBlob *blob)
-: SecurityServerAcl(keyAcl, CssmAllocator::standard()), mDigest(Server::csp().allocator())
-{
- // perform basic validation on the incoming blob
- assert(blob);
- blob->validate(CSSMERR_APPLEDL_INVALID_KEY_BLOB);
- switch (blob->version()) {
-#if defined(COMPAT_OSX_10_0)
- case blob->version_MacOS_10_0:
- break;
-#endif
- case blob->version_MacOS_10_1:
- break;
- default:
- CssmError::throwMe(CSSMERR_APPLEDL_INCOMPATIBLE_KEY_BLOB);
- }
-
- // set it up
- mDatabase = &db;
- mBlob = blob->copy(CssmAllocator::standard());
- mAttributes = 0;
- mValidBlob = true;
- mValidKey = false;
- mValidUID = false;
- secdebug("SSkey", "%p (handle 0x%lx) created from blob version %lx",
- this, handle(), blob->version());
-}
-
-
-//
-// Create a Key from an explicit CssmKey.
-//
-Key::Key(Database *db, const CssmKey &newKey, uint32 moreAttributes,
- const AclEntryPrototype *owner)
-: SecurityServerAcl(keyAcl, CssmAllocator::standard()), mDigest(Server::csp().allocator())
-{
- if (moreAttributes & CSSM_KEYATTR_PERMANENT) {
- // better have a database to make it permanent in...
- if (!db)
- CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE);
- } else {
- // non-permanent; ignore database
- db = NULL;
- }
-
- mDatabase = db;
- mValidKey = true;
- mBlob = NULL;
- mValidBlob = false;
- mValidUID = false;
- setup(newKey, moreAttributes);
-
- // establish initial ACL; reinterpret empty (null-list) owner as NULL for resilence's sake
- if (owner && !owner->subject().empty())
- cssmSetInitial(*owner); // specified
- else
- cssmSetInitial(new AnyAclSubject()); // defaulted
- secdebug("SSkey", "%p (handle 0x%lx) created from key alg=%ld use=0x%lx attr=0x%lx db=%p",
- this, handle(), mKey.header().algorithm(), mKey.header().usage(), mAttributes, db);
-}
-
-
-//
-// Set up the CssmKey part of this Key according to instructions.
-//
-void Key::setup(const CssmKey &newKey, uint32 moreAttributes)
-{
- mKey = CssmClient::Key(Server::csp(), newKey, false);
- CssmKey::Header &header = mKey->header();
-
- // copy key header
- header = newKey.header();
- mAttributes = (header.attributes() & ~forcedAttributes) | moreAttributes;
-
- // apply initial values of derived attributes (these are all in managedAttributes)
- if (!(mAttributes & CSSM_KEYATTR_EXTRACTABLE))
- mAttributes |= CSSM_KEYATTR_NEVER_EXTRACTABLE;
- if (mAttributes & CSSM_KEYATTR_SENSITIVE)
- mAttributes |= CSSM_KEYATTR_ALWAYS_SENSITIVE;
-
- // verify internal/external attribute separation
- assert((header.attributes() & managedAttributes) == forcedAttributes);
-}
-
-
-Key::~Key()
-{
- CssmAllocator::standard().free(mBlob);
- secdebug("SSkey", "%p destroyed", this);
-}
-
-
-//
-// Form a KeySpec with checking and masking
-//
-Key::KeySpec::KeySpec(uint32 usage, uint32 attrs)
- : CssmClient::KeySpec(usage, (attrs & ~managedAttributes) | forcedAttributes)
-{
- if (attrs & generatedAttributes)
- CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
-}
-
-Key::KeySpec::KeySpec(uint32 usage, uint32 attrs, const CssmData &label)
- : CssmClient::KeySpec(usage, (attrs & ~managedAttributes) | forcedAttributes, label)
-{
- if (attrs & generatedAttributes)
- CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
-}
-
-
-//
-// Retrieve the actual CssmKey value for the key object.
-// This will decode its blob if needed (and appropriate).
-//
-CssmClient::Key Key::keyValue()
-{
- decode();
- return mKey;
-}
-
-
-//
-// Ensure that a key is fully decoded.
-// This makes the mKey key value available for use, as well as its ACL.
-//
-void Key::decode()
-{
- if (!mValidKey) {
- assert(mDatabase); // have to have a database (to decode the blob)
- assert(mValidBlob); // must have a blob to decode
-
- // decode the key
- void *publicAcl, *privateAcl;
- CssmKey key;
- database()->decodeKey(mBlob, key, publicAcl, privateAcl);
- mKey = CssmClient::Key(Server::csp(), key);
- importBlob(publicAcl, privateAcl);
- // publicAcl points into the blob; privateAcl was allocated for us
- CssmAllocator::standard().free(privateAcl);
-
- // extract managed attribute bits
- mAttributes = mKey.header().attributes() & managedAttributes;
- mKey.header().clearAttribute(managedAttributes);
- mKey.header().setAttribute(forcedAttributes);
-
- // key is valid now
- mValidKey = true;
- }
-}
-
-
-//
-// Return a key's handle and header in external form
-//
-void Key::returnKey(Handle &h, CssmKey::Header &hdr)
-{
- // return handle
- h = handle();
-
- // obtain the key header, from the valid key or the blob if no valid key
- if (mValidKey) {
- hdr = mKey.header();
- } else {
- assert(mValidBlob);
- hdr = mBlob->header;
- n2hi(hdr); // correct for endian-ness
- }
-
- // adjust for external attributes
- hdr.clearAttribute(forcedAttributes);
- hdr.setAttribute(mAttributes);
-}
-
-
-//
-// Generate the canonical key digest.
-// This is defined by a CSP feature that we invoke here.
-//
-const CssmData &Key::canonicalDigest()
-{
- 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); // takes ownership of digest data
- Server::csp().allocator().free(digest); // the CssmData itself
- }
- return mDigest.get();
-}
-
-
-//
-// Encode a key into a blob.
-// We'll have to ask our Database to do this - we don't have its keys.
-// Note that this returns memory we own and keep.
-//
-KeyBlob *Key::blob()
-{
- if (mDatabase == NULL) // can't encode independent keys
- CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE);
- if (!mValidBlob) {
- assert(mValidKey); // must have valid key to encode
- //@@@ release mBlob memory here
-
- // export Key ACL to blob form
- CssmData pubAcl, privAcl;
- exportBlob(pubAcl, privAcl);
-
- // assemble external key form
- CssmKey externalKey = mKey;
- externalKey.clearAttribute(forcedAttributes);
- externalKey.setAttribute(mAttributes);
-
- // encode the key and replace blob
- KeyBlob *newBlob = database()->encodeKey(externalKey, pubAcl, privAcl);
- CssmAllocator::standard().free(mBlob);
- mBlob = newBlob;
- mValidBlob = true;
-
- // clean up and go
- database()->allocator.free(pubAcl);
- database()->allocator.free(privAcl);
- }
- return mBlob;
-}
-
-
-//
-// Return the UID of a key (the hash of its bits)
-//
-KeyUID &Key::uid()
-{
- if (!mValidUID) {
- //@@@ calculate UID here
- memset(&mUID, 0, sizeof(mUID));
- mValidUID = true;
- }
- return mUID;
-}
-
-
-//
-// Intercept ACL change requests and reset blob validity
-//
-void Key::instantiateAcl()
-{
- decode();
-}
-
-void Key::changedAcl()
-{
- mValidBlob = false;
-}
-
-const Database *Key::relatedDatabase() const
-{ return database(); }