]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/muscle++.cpp
Security-58286.200.222.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / muscle++.cpp
1 /*
2 * Copyright (c) 2004,2011-2012,2014 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 //
27 // C++ gate to "Muscle" smartcard interface layer
28 //
29 #include "muscle++.h"
30 #include <security_utilities/debugging.h>
31
32 #if TARGET_OS_OSX
33
34 namespace Security {
35 namespace Muscle {
36
37
38 //
39 // PCSC domain errors
40 //
41 Error::Error(MSC_RV err) : error(err)
42 {
43 SECURITY_EXCEPTION_THROW_OTHER(this, err, (char *)"muscle");
44 secnotice("security_exception", "muscle: %d", err);
45 }
46
47
48 const char *Error::what() const throw ()
49 {
50 return msc_error(error);
51 }
52
53
54 void Error::throwMe(MSC_RV err)
55 {
56 throw Error(err);
57 }
58
59
60 OSStatus Error::osStatus() const
61 {
62 return -1; //@@@ preliminary
63 }
64
65 int Error::unixError() const
66 {
67 return EINVAL; //@@@ preliminary
68 }
69
70
71 //
72 // Open a connection with PCSC layer information.
73 // The ReaderState fields required are the slot name and the ATR.
74 //
75 Connection::Connection()
76 : mIsOpen(false), mCurrentTransaction(NULL)
77 {
78 }
79
80 Connection::~Connection()
81 {
82 assert(!mCurrentTransaction);
83 close();
84 }
85
86 void Connection::open(const PCSC::ReaderState &reader, unsigned share)
87 {
88 // fill in the minimum needed to identify the card
89 MSCTokenInfo info;
90
91 // set slot name in info
92 strncpy(info.slotName, reader.name(), MAX_READERNAME);
93
94 // set ATR in info
95 assert(reader.length() <= MAX_ATR_SIZE);
96 memcpy(info.tokenId, reader.data(), reader.length());
97 info.tokenIdLength = (MSCULong32)reader.length();
98
99 // establish Muscle-level connection to card
100 Error::check(::MSCEstablishConnection(&info, share, NULL, 0, this));
101 mIsOpen = true;
102 secinfo("muscle", "%p opened %s", this, info.slotName);
103
104 // pull initial status
105 updateStatus();
106 }
107
108 void Connection::close()
109 {
110 if (mIsOpen) {
111 secinfo("muscle", "%p closing", this);
112 Error::check(::MSCReleaseConnection(this, SCARD_LEAVE_CARD));
113 mIsOpen = false;
114 }
115 }
116
117
118 void Connection::begin(Transaction *trans)
119 {
120 assert(!mCurrentTransaction);
121 Error::check(::MSCBeginTransaction(this));
122 secinfo("muscle", "%p start transaction %p", this, trans);
123 mCurrentTransaction = trans;
124 }
125
126 void Connection::end(Transaction *trans)
127 {
128 assert(trans == mCurrentTransaction);
129 secinfo("muscle", "%p end transaction %p", this, trans);
130 Error::check(::MSCEndTransaction(this, SCARD_LEAVE_CARD));
131 mCurrentTransaction = NULL;
132 }
133
134
135 //
136 // Update card status (cached in the Connection object)
137 //
138 void Connection::updateStatus()
139 {
140 Error::check(::MSCGetStatus(this, this));
141 }
142
143
144 //
145 // Get all items off the card
146 //
147 template <class Info, class Item, MSC_RV (*list)(MSCTokenConnection *, MSCUChar8, Info *)>
148 static void get(Connection *conn, Connection::ItemSet &items)
149 {
150 Info info;
151 MSCUChar8 seq = MSC_SEQUENCE_RESET;
152 for (;;) {
153 switch (MSC_RV rc = list(conn, seq, &info)) {
154 case MSC_SEQUENCE_END:
155 return;
156 case MSC_SUCCESS:
157 items.insert(new Item(info));
158 seq = MSC_SEQUENCE_NEXT;
159 break;
160 default:
161 Error::throwMe(rc);
162 }
163 }
164 }
165
166 void Connection::getItems(ItemSet &result, bool getKeys, bool getOthers)
167 {
168 ItemSet items;
169 if (getKeys)
170 get<MSCKeyInfo, Key, MSCListKeys>(this, items);
171 if (getOthers)
172 get<MSCObjectInfo, Object, MSCListObjects>(this, items);
173 items.swap(result);
174 }
175
176
177 //
178 // Transaction monitors
179 //
180 Transaction::Transaction(Connection &con)
181 : connection(con)
182 {
183 connection.begin(this);
184 }
185
186 Transaction::~Transaction()
187 {
188 connection.end(this);
189 }
190
191
192 //
193 // ACLs (Muscle style)
194 //
195 static void aclForm(string &s, MSCUShort16 acl, int offset, char c)
196 {
197 for (int n = 0; n < 5; n++) {
198 char p = '-';
199 switch (acl) {
200 case MSC_AUT_ALL: p = c; break;
201 case MSC_AUT_NONE: break;
202 default: if (acl & (MSC_AUT_PIN_0 << n)) p = c; break;
203 }
204 s[3 * n + offset] = p;
205 }
206 }
207
208 string ACL::form(char ue) const
209 {
210 string r = "---------------";
211 aclForm(r, mRead, 0, 'r');
212 aclForm(r, mWrite, 1, 'w');
213 aclForm(r, mErase, 2, ue);
214 return r;
215 }
216
217
218 //
219 // Keys and objects
220 //
221 CardItem::~CardItem()
222 { /* virtual */ }
223
224
225 Key::Key(const MSCKeyInfo &info)
226 : MSCKeyInfo(info)
227 {
228 snprintf(mKeyName, sizeof(mKeyName), "K%d", id());
229 }
230
231
232 const ACL &Key::acl() const { return reinterpret_cast<const ACL &>(keyACL); }
233 ACL &Key::acl() { return reinterpret_cast<ACL &>(keyACL); }
234
235 const char *Key::name() const { return mKeyName; }
236 unsigned Key::size() const { return keySize; }
237
238 void Key::debugDump()
239 {
240 printf("Key %d type %d size %d mode=0x%x dir=0x%x ACL %s\n",
241 keyNum, keyType, keySize, mode(), operations(), acl().form('u').c_str());
242 }
243
244 const char *Object::name() const { return objectID; }
245 unsigned Object::size() const { return objectSize; }
246
247 const ACL &Object::acl() const { return reinterpret_cast<const ACL &>(objectACL); }
248 ACL &Object::acl() { return reinterpret_cast<ACL &>(objectACL); }
249
250 void Object::debugDump()
251 {
252 printf("Object %s size %d ACL %s\n",
253 objectID, objectSize, acl().form('e').c_str());
254 }
255
256
257 } // namespace Muscle
258 } // namespace Security
259
260 #endif //TARGET_OS_OSX