]> git.saurik.com Git - apple/securityd.git/blob - src/kckey.cpp
securityd-16.tar.gz
[apple/securityd.git] / src / kckey.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26
27 //
28 // key - representation of SecurityServer key objects
29 //
30 #include "kckey.h"
31 #include "server.h"
32 #include "database.h"
33 #include <security_cdsa_utilities/acl_any.h>
34
35
36 //
37 // Create a Key object from a database-encoded blob.
38 // Note that this doesn't decode the blob (yet).
39 //
40 KeychainKey::KeychainKey(Database &db, const KeyBlob *blob)
41 : LocalKey(db)
42 {
43 // perform basic validation on the incoming blob
44 assert(blob);
45 blob->validate(CSSMERR_APPLEDL_INVALID_KEY_BLOB);
46 switch (blob->version()) {
47 #if defined(COMPAT_OSX_10_0)
48 case blob->version_MacOS_10_0:
49 break;
50 #endif
51 case blob->version_MacOS_10_1:
52 break;
53 default:
54 CssmError::throwMe(CSSMERR_APPLEDL_INCOMPATIBLE_KEY_BLOB);
55 }
56
57 // set it up
58 mBlob = blob->copy(Allocator::standard());
59 mValidBlob = true;
60 db.addReference(*this);
61 secdebug("SSkey", "%p (handle 0x%lx) created from blob version %lx",
62 this, handle(), blob->version());
63 }
64
65
66 //
67 // Create a Key from an explicit CssmKey.
68 //
69 KeychainKey::KeychainKey(Database &db, const CssmKey &newKey, uint32 moreAttributes,
70 const AclEntryPrototype *owner)
71 : LocalKey(db, newKey, moreAttributes, owner)
72 {
73 assert(moreAttributes & CSSM_KEYATTR_PERMANENT);
74 mBlob = NULL;
75 mValidBlob = false;
76 db.addReference(*this);
77 }
78
79
80 KeychainKey::~KeychainKey()
81 {
82 Allocator::standard().free(mBlob);
83 secdebug("SSkey", "%p destroyed", this);
84 }
85
86
87 KeychainDatabase &KeychainKey::database() const
88 {
89 return referent<KeychainDatabase>();
90 }
91
92
93 //
94 // Retrieve the actual CssmKey value for the key object.
95 // This will decode its blob if needed (and appropriate).
96 //
97 void KeychainKey::getKey()
98 {
99 decode();
100 }
101
102 void KeychainKey::getHeader(CssmKey::Header &hdr)
103 {
104 assert(mValidBlob);
105 hdr = mBlob->header;
106 n2hi(hdr); // correct for endian-ness
107 }
108
109
110 //
111 // Ensure that a key is fully decoded.
112 // This makes the mKey key value available for use, as well as its ACL.
113 //
114 void KeychainKey::decode()
115 {
116 if (!mValidKey) {
117 assert(mValidBlob); // must have a blob to decode
118
119 // decode the key
120 void *publicAcl, *privateAcl;
121 CssmKey key;
122 database().decodeKey(mBlob, key, publicAcl, privateAcl);
123 mKey = CssmClient::Key(Server::csp(), key);
124 importBlob(publicAcl, privateAcl);
125 // publicAcl points into the blob; privateAcl was allocated for us
126 Allocator::standard().free(privateAcl);
127
128 // extract managed attribute bits
129 mAttributes = mKey.header().attributes() & managedAttributes;
130 mKey.header().clearAttribute(managedAttributes);
131 mKey.header().setAttribute(forcedAttributes);
132
133 // key is valid now
134 mValidKey = true;
135 }
136 }
137
138
139 //
140 // Encode a key into a blob.
141 // We'll have to ask our Database to do this - we don't have its keys.
142 // Note that this returns memory we own and keep.
143 //
144 KeyBlob *KeychainKey::blob()
145 {
146 if (!mValidBlob) {
147 assert(mValidKey); // must have valid key to encode
148 //@@@ release mBlob memory here
149
150 // export Key ACL to blob form
151 CssmData pubAcl, privAcl;
152 exportBlob(pubAcl, privAcl);
153
154 // assemble external key form
155 CssmKey externalKey = mKey;
156 externalKey.clearAttribute(forcedAttributes);
157 externalKey.setAttribute(mAttributes);
158
159 // encode the key and replace blob
160 KeyBlob *newBlob = database().encodeKey(externalKey, pubAcl, privAcl);
161 Allocator::standard().free(mBlob);
162 mBlob = newBlob;
163 mValidBlob = true;
164
165 // clean up and go
166 database().allocator.free(pubAcl);
167 database().allocator.free(privAcl);
168 }
169 return mBlob;
170 }
171
172
173 //
174 // Intercept ACL change requests and reset blob validity
175 //
176 void KeychainKey::instantiateAcl()
177 {
178 decode();
179 }
180
181 void KeychainKey::changedAcl()
182 {
183 mValidBlob = false;
184 }
185
186 const Database *KeychainKey::relatedDatabase() const
187 { return &database(); }