1/*
2 * Copyright (c) 2000-2001,2004,2006-2008 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25//
26// localkey - Key objects that store a local CSSM key object
27//
28#include "localkey.h"
29#include "server.h"
30#include "database.h"
31#include <security_cdsa_utilities/acl_any.h>
32
33
34//
35// Create a Key from an explicit CssmKey.
36//
37LocalKey::LocalKey(Database &db, const CssmKey &newKey, CSSM_KEYATTR_FLAGS moreAttributes)
38	: Key(db), mDigest(Server::csp().allocator())
39{
40	mValidKey = true;
41	setup(newKey, moreAttributes);
42    secdebug("SSkey", "%p (handle %#x) created from key alg=%u use=0x%x attr=0x%x db=%p",
43        this, handle(), mKey.header().algorithm(), mKey.header().usage(), mAttributes, &db);
44}
45
46
47LocalKey::LocalKey(Database &db, CSSM_KEYATTR_FLAGS attributes)
48	: Key(db), mValidKey(false), mAttributes(attributes), mDigest(Server::csp().allocator())
49{
50}
51
52
53//
54// Set up the CssmKey part of this Key according to instructions.
55//
56void LocalKey::setup(const CssmKey &newKey, CSSM_KEYATTR_FLAGS moreAttributes)
57{
58	mKey = CssmClient::Key(Server::csp(), newKey, false);
59    CssmKey::Header &header = mKey->header();
60
61	// copy key header
62	header = newKey.header();
63    mAttributes = (header.attributes() & ~forcedAttributes) | moreAttributes;
64
65	// apply initial values of derived attributes (these are all in managedAttributes)
66    if (!(mAttributes & CSSM_KEYATTR_EXTRACTABLE))
67        mAttributes |= CSSM_KEYATTR_NEVER_EXTRACTABLE;
68    if (mAttributes & CSSM_KEYATTR_SENSITIVE)
69        mAttributes |= CSSM_KEYATTR_ALWAYS_SENSITIVE;
70
71    // verify internal/external attribute separation
72    assert((header.attributes() & managedAttributes) == forcedAttributes);
73}
74
75
76LocalKey::~LocalKey()
77{
78    secdebug("SSkey", "%p destroyed", this);
79}
80
81
82void LocalKey::setOwner(const AclEntryPrototype *owner)
83{
84	// establish initial ACL; reinterpret empty (null-list) owner as NULL for resilence's sake
85	if (owner && !owner->subject().empty())
86		acl().cssmSetInitial(*owner);					// specified
87	else
88		acl().cssmSetInitial(new AnyAclSubject());		// defaulted
89}
90
91
92LocalDatabase &LocalKey::database() const
93{
94	return referent<LocalDatabase>();
95}
96
97
98//
99// Retrieve the actual CssmKey value for the key object.
100// This will decode its blob if needed (and appropriate).
101//
102CssmClient::Key LocalKey::keyValue()
103{
104	StLock<Mutex> _(*this);
105    if (!mValidKey) {
106		getKey();
107		mValidKey = true;
108	}
109    return mKey;
110}
111
112
113//
114// Return external key attributees
115//
116CSSM_KEYATTR_FLAGS LocalKey::attributes()
117{
118	return mAttributes;
119}
120
121
122//
123// Return a key's handle and header in external form
124//
125void LocalKey::returnKey(U32HandleObject::Handle &h, CssmKey::Header &hdr)
126{
127	StLock<Mutex> _(*this);
128
129    // return handle
130    h = this->handle();
131
132	// obtain the key header, from the valid key or the blob if no valid key
133	if (mValidKey) {
134		hdr = mKey.header();
135	} else {
136		getHeader(hdr);
137	}
138
139    // adjust for external attributes
140	hdr.clearAttribute(forcedAttributes);
141    hdr.setAttribute(mAttributes);
142}
143
144
145//
146// Generate the canonical key digest.
147// This is defined by a CSP feature that we invoke here.
148//
149const CssmData &LocalKey::canonicalDigest()
150{
151	StLock<Mutex> _(*this);
152	if (!mDigest) {
153		CssmClient::PassThrough ctx(Server::csp());
154		ctx.key(keyValue());
155		CssmData *digest = NULL;
156		ctx(CSSM_APPLECSP_KEYDIGEST, (const void *)NULL, &digest);
157		assert(digest);
158		mDigest.set(*digest);	// takes ownership of digest data
159		Server::csp().allocator().free(digest);	// the CssmData itself
160	}
161	return mDigest.get();
162}
163
164
165//
166// Default getKey/getHeader calls - should never be called
167//
168void LocalKey::getKey()
169{
170	assert(false);
171}
172
173void LocalKey::getHeader(CssmKey::Header &)
174{
175	assert(false);
176}
177
178
179//
180// Form a KeySpec with checking and masking
181//
182LocalKey::KeySpec::KeySpec(CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs)
183	: CssmClient::KeySpec(usage, (attrs & ~managedAttributes) | forcedAttributes)
184{
185	if (attrs & generatedAttributes)
186		CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
187}
188
189LocalKey::KeySpec::KeySpec(CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, const CssmData &label)
190	: CssmClient::KeySpec(usage, (attrs & ~managedAttributes) | forcedAttributes, label)
191{
192	if (attrs & generatedAttributes)
193		CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
194}
195