1/*
2 * Copyright (c) 2004 Apple Computer, 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// pcsc++ - PCSC client interface layer in C++
27//
28// NOTE: TO BE MOVED TO security_utilities LAYER.
29//
30#ifndef _H_PCSC_PP
31#define _H_PCSC_PP
32
33#include <security_utilities/utilities.h>
34#include <security_utilities/errors.h>
35#include <security_utilities/transactions.h>
36#include <security_utilities/debugging.h>
37#include <PCSC/winscard.h>
38#include <vector>
39#include <string>
40
41#include <cstdio>
42
43
44namespace Security {
45namespace PCSC {
46
47
48//
49// PCSC-domain error exceptions
50//
51class Error : public CommonError {
52public:
53	Error(unsigned long err);
54
55    const unsigned long error;
56	OSStatus osStatus() const;
57	int unixError() const;
58	const char *what () const throw ();
59
60	static void check(unsigned long err) { if (err != SCARD_S_SUCCESS) throwMe(err); }
61	static void throwMe(unsigned long err);
62};
63
64
65//
66// A PODWrapper for the PCSC READERSTATE structure
67//
68class ReaderState : public PodWrapper<ReaderState, SCARD_READERSTATE> {
69public:
70	void set(const char *name, unsigned long known = SCARD_STATE_UNAWARE);
71
72	const char *name() const	{ return szReader; }
73	void name(const char *s)	{ szReader = s; }
74
75	unsigned long lastKnown() const { return dwCurrentState; }
76	void lastKnown(unsigned long s);
77
78	unsigned long state() const { return dwEventState; }
79	bool state(unsigned long it) const { return state() & it; }
80	bool changed() const		{ return state(SCARD_STATE_CHANGED); }
81
82	template <class T>
83	T * &userData() { return reinterpret_cast<T * &>(pvUserData); }
84
85	// DataOid access to the ATR data
86	const void *data() const { return rgbAtr; }
87	size_t length() const { return cbAtr; }
88	void setATR(const void *atr, size_t size);
89
90	IFDUMP(void dump());
91};
92
93
94//
95// A Session represents the entire process state for the PCSC protocol
96//
97class Session {
98	friend class Card;
99public:
100	Session();
101	virtual ~Session();
102
103	void open();
104	void close();
105	bool isOpen() const { return mIsOpen; }
106
107	void listReaders(vector<string> &readers, const char *groups = NULL);
108
109	void statusChange(ReaderState *readers, unsigned int nReaders, long timeout = 0);
110	void statusChange(ReaderState &reader, long timeout = 0)
111	{ return statusChange(&reader, 1, timeout); }
112	void statusChange(vector<ReaderState> &readers, long timeout = 0)
113	{ return statusChange(&readers[0], (unsigned int)readers.size(), timeout); }
114
115
116private:
117	bool check(long rc);
118
119private:
120	bool mIsOpen;
121	SCARDCONTEXT mContext;
122	std::vector<char> mReaderBuffer;
123};
124
125
126//
127// A Card represents a PCSC-managed card slot
128//
129class Card {
130public:
131	static const unsigned long defaultProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
132
133	Card();
134	virtual ~Card();
135
136	void connect(Session &session, const char *reader,
137		unsigned long share = SCARD_SHARE_SHARED,
138		unsigned long protocols = defaultProtocols);
139	void reconnect(unsigned long share = SCARD_SHARE_SHARED,
140		unsigned long protocols = defaultProtocols,
141		unsigned long initialization = SCARD_LEAVE_CARD);
142	void disconnect(unsigned long disposition = SCARD_LEAVE_CARD);
143	virtual void didDisconnect();
144	virtual void didEnd();
145
146	void checkReset(unsigned int rv);
147	bool isConnected() const { return mConnectedState == kConnected; }
148	bool isInTransaction() const { return mTransactionNestLevel > 0; }
149
150	void transmit(const unsigned char *pbSendBuffer, size_t cbSendLength,
151		unsigned char *pbRecvBuffer, size_t &pcbRecvLength);
152
153	// primitive transaction interface
154	void begin();
155	void end(unsigned long disposition = SCARD_LEAVE_CARD);
156	void cancel();
157
158protected:
159	void setIOType(unsigned long activeProtocol);
160
161	IFDUMP(void dump(const char *direction, const unsigned char *buffer, size_t length);)
162
163private:
164	enum
165	{
166		kInitial,
167		kConnected,
168		kDisconnected
169	} mConnectedState;
170
171	int32_t mHandle;
172	int mTransactionNestLevel;
173	SCARD_IO_REQUEST *mIOType;
174};
175
176
177//
178// A PCSC-layer transaction (exclusive sequence of calls)
179//
180class Transaction : public ManagedTransaction<Card> {
181public:
182	Transaction(Card &card, Outcome outcome = conditional)
183		: ManagedTransaction<Card>(card, outcome), mDisposition(SCARD_LEAVE_CARD) { }
184
185	void disposition(unsigned long disp);	// change disposition on successful outcome
186
187protected:
188	void commitAction();
189
190private:
191	unsigned long mDisposition;				// disposition on success
192};
193
194
195}   // namespce PCSC
196}   // namespace Security
197
198
199#endif //_H_PCSC_PP
200