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