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