]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_utilities/lib/muscle++.cpp
Security-58286.1.32.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
866f8763 32#if TARGET_OS_OSX
b1ab9ed8
A
33
34namespace Security {
35namespace Muscle {
36
37
38//
39// PCSC domain errors
40//
41Error::Error(MSC_RV err) : error(err)
42{
fa7225c8
A
43 SECURITY_EXCEPTION_THROW_OTHER(this, err, (char *)"muscle");
44 secnotice("security_exception", "muscle: %d", err);
b1ab9ed8
A
45}
46
47
48const char *Error::what() const throw ()
49{
50 return msc_error(error);
51}
52
53
54void Error::throwMe(MSC_RV err)
55{
56 throw Error(err);
57}
58
59
60OSStatus Error::osStatus() const
61{
62 return -1; //@@@ preliminary
63}
64
65int 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//
75Connection::Connection()
76 : mIsOpen(false), mCurrentTransaction(NULL)
77{
78}
79
80Connection::~Connection()
81{
82 assert(!mCurrentTransaction);
83 close();
84}
85
86void 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());
427c49bc 97 info.tokenIdLength = (MSCULong32)reader.length();
b1ab9ed8
A
98
99 // establish Muscle-level connection to card
100 Error::check(::MSCEstablishConnection(&info, share, NULL, 0, this));
101 mIsOpen = true;
fa7225c8 102 secinfo("muscle", "%p opened %s", this, info.slotName);
b1ab9ed8
A
103
104 // pull initial status
105 updateStatus();
106}
107
108void Connection::close()
109{
110 if (mIsOpen) {
fa7225c8 111 secinfo("muscle", "%p closing", this);
b1ab9ed8
A
112 Error::check(::MSCReleaseConnection(this, SCARD_LEAVE_CARD));
113 mIsOpen = false;
114 }
115}
116
117
118void Connection::begin(Transaction *trans)
119{
120 assert(!mCurrentTransaction);
121 Error::check(::MSCBeginTransaction(this));
fa7225c8 122 secinfo("muscle", "%p start transaction %p", this, trans);
b1ab9ed8
A
123 mCurrentTransaction = trans;
124}
125
126void Connection::end(Transaction *trans)
127{
128 assert(trans == mCurrentTransaction);
fa7225c8 129 secinfo("muscle", "%p end transaction %p", this, trans);
b1ab9ed8
A
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//
138void Connection::updateStatus()
139{
140 Error::check(::MSCGetStatus(this, this));
141}
142
143
144//
145// Get all items off the card
146//
147template <class Info, class Item, MSC_RV (*list)(MSCTokenConnection *, MSCUChar8, Info *)>
148static 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
166void 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//
180Transaction::Transaction(Connection &con)
181 : connection(con)
182{
183 connection.begin(this);
184}
185
186Transaction::~Transaction()
187{
188 connection.end(this);
189}
190
191
192//
193// ACLs (Muscle style)
194//
195static 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
208string 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//
221CardItem::~CardItem()
222{ /* virtual */ }
223
224
225Key::Key(const MSCKeyInfo &info)
226 : MSCKeyInfo(info)
227{
228 snprintf(mKeyName, sizeof(mKeyName), "K%d", id());
229}
230
231
232const ACL &Key::acl() const { return reinterpret_cast<const ACL &>(keyACL); }
233ACL &Key::acl() { return reinterpret_cast<ACL &>(keyACL); }
234
235const char *Key::name() const { return mKeyName; }
236unsigned Key::size() const { return keySize; }
237
238void 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
244const char *Object::name() const { return objectID; }
245unsigned Object::size() const { return objectSize; }
246
247const ACL &Object::acl() const { return reinterpret_cast<const ACL &>(objectACL); }
248ACL &Object::acl() { return reinterpret_cast<ACL &>(objectACL); }
249
250void 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
866f8763
A
259
260#endif //TARGET_OS_OSX