Apply coding rule
[platform/core/connectivity/smartcard-service.git] / common / FileObject.cpp
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /* standard library header */
18 #include <stdio.h>
19 #include <glib.h>
20
21 /* SLP library header */
22
23 /* local header */
24 #include "Debug.h"
25 #include "FileObject.h"
26 #include "APDUHelper.h"
27
28 namespace smartcard_service_api
29 {
30         FileObject::FileObject(Channel *channel)
31                 : ProviderHelper(channel)
32         {
33                 opened = false;
34         }
35
36         FileObject::FileObject(Channel *channel, const ByteArray &selectResponse)
37                 : ProviderHelper(channel)
38         {
39                 opened = false;
40                 setSelectResponse(selectResponse);
41         }
42
43         FileObject::~FileObject()
44         {
45                 close();
46         }
47
48         void FileObject::close()
49         {
50                 opened = false;
51                 selectResponse.clear();
52         }
53
54         bool FileObject::setSelectResponse(const ByteArray &response)
55         {
56                 bool result = false;
57
58                 if (response.size() >= 2) {
59                         ResponseHelper resp(response);
60                         selectResponse = response;
61
62                         if (resp.getStatus() >= 0) {
63                                 fcp.releaseFCP();
64
65                                 fcp.setFCP(resp.getDataField());
66
67                                 _DBG("FCP : %s", fcp.toString().c_str());
68
69                                 opened = true;
70                                 result = true;
71                         } else {
72                                 _ERR("status word [ %02X %02X ]",
73                                         resp.getSW1(), resp.getSW2());
74                         }
75                 } else {
76                         _ERR("invalid response");
77                 }
78
79                 return result;
80         }
81
82         int FileObject::_select(const ByteArray &command)
83         {
84                 int ret = ERROR_ILLEGAL_STATE;
85                 ByteArray result;
86
87                 if (channel == NULL || channel->isClosed())
88                 {
89                         _ERR("channel is not open");
90
91                         return ret;
92                 }
93
94                 close();
95
96                 ret = channel->transmitSync(command, result);
97                 if (ret == 0) {
98                         ResponseHelper resp(result);
99
100                         ret = resp.getStatus();
101
102                         setSelectResponse(result);
103                 } else {
104                         _ERR("select apdu is failed, rv [%d], length [%d]",
105                                 ret, result.size());
106
107                         ret = ERROR_ILLEGAL_STATE;
108                 }
109
110                 return ret;
111         }
112
113         int FileObject::select(const ByteArray &aid)
114         {
115                 int ret = ERROR_ILLEGAL_STATE;
116                 ByteArray command;
117
118                 /* make apdu command */
119                 command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_DF_NAME, 0, aid);
120
121                 ret = _select(command);
122
123                 return ret;
124         }
125
126         int FileObject::select(const ByteArray &path, bool fromCurrentDF)
127         {
128                 int ret = ERROR_ILLEGAL_STATE;
129                 ByteArray command;
130
131                 /* make apdu command */
132                 if (fromCurrentDF == true) {
133                         command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_PATH_FROM_CURRENT_DF, 0, path);
134                 } else {
135                         ByteArray temp(path);
136
137                         if (path.size() > 2 && path[0] == 0x3f && path[1] == 0x00) /* check MF */ {
138                                 /* remove MF from path */
139                                 temp.assign(path.getBuffer(2), path.size() - 2);
140                         }
141
142                         command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_PATH, 0, temp);
143                 }
144
145                 ret = _select(command);
146
147                 return ret;
148         }
149
150         int FileObject::select(unsigned int fid)
151         {
152                 int ret = ERROR_ILLEGAL_STATE;
153                 ByteArray command, fidData((unsigned char *)&fid, 2);
154
155                 /* make apdu command */
156                 command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_ID, 0, fidData);
157
158                 ret = _select(command);
159
160                 return ret;
161         }
162
163         int FileObject::selectParent()
164         {
165                 int ret = ERROR_ILLEGAL_STATE;
166                 ByteArray command;
167
168                 /* make apdu command */
169                 command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_PARENT_DF, 0, ByteArray::EMPTY);
170
171                 ret = _select(command);
172
173                 return ret;
174         }
175
176         const FCI *FileObject::getFCI() const
177         {
178                 return NULL;
179         }
180
181         const FCP *FileObject::getFCP() const
182         {
183                 return &fcp;
184         }
185
186         int FileObject::readRecord(unsigned int sfi, unsigned int recordId, Record &result)
187         {
188                 ByteArray command, response;
189                 APDUCommand apdu;
190                 int ret;
191
192                 apdu.setCommand(0, APDUCommand::INS_READ_RECORD, recordId, 4, ByteArray::EMPTY, APDUCommand::LE_MAX);
193                 apdu.getBuffer(command);
194
195                 ret = channel->transmitSync(command, response);
196                 if (ret == 0 && response.size() >= 2) {
197                         ResponseHelper resp(response);
198
199                         ret = resp.getStatus();
200                         if (ret >= 0) {
201                                 _DBG("response [%d] : %s", response.size(), response.toString().c_str());
202
203                                 result = Record(recordId, resp.getDataField());
204                         } else {
205                                 _ERR("status word [ %02X %02X ]", resp.getSW1(), resp.getSW2());
206                         }
207                 } else {
208                         _ERR("select apdu is failed, rv [%d], length [%d]", ret, response.size());
209                 }
210
211                 return ret;
212         }
213
214         int FileObject::writeRecord(unsigned int sfi, const Record &record)
215         {
216                 return 0;
217         }
218
219         int FileObject::searchRecord(unsigned int sfi, const ByteArray &searchParam, vector<int> &result)
220         {
221                 return 0;
222         }
223
224 #define MAX_SINGLE_LEN  256
225
226         int FileObject::readBinary(unsigned int sfi, unsigned int offset, unsigned int length, ByteArray &result)
227         {
228                 ByteArray command, response;
229                 APDUCommand apdu;
230                 int ret;
231
232                 /* FIXME : fix calculating length */
233                 apdu.setCommand(0, APDUCommand::INS_READ_BINARY,
234                         (offset >> 8) & 0x7F, offset & 0x00FF,
235                         ByteArray::EMPTY, (length > MAX_SINGLE_LEN - 1) ? 0 : length);
236
237                 apdu.getBuffer(command);
238
239                 ret = channel->transmitSync(command, response);
240                 if (ret == 0 && response.size() >= 2) {
241                         ResponseHelper resp(response);
242
243                         if (resp.getStatus() >= 0) {
244                                 _DBG("response [%d] : %s", response.size(), response.toString().c_str());
245
246                                 result = resp.getDataField();
247
248                                 ret = SUCCESS;
249                         } else {
250                                 _ERR("status word [ %02X %02X ]", resp.getSW1(), resp.getSW2());
251                         }
252                 } else {
253                         _ERR("select apdu is failed, rv [%d], length [%d]", ret, response.size());
254                 }
255
256                 return ret;
257         }
258
259         int FileObject::readBinary(unsigned int sfi, unsigned int length, ByteArray &result)
260         {
261                 int ret;
262                 size_t offset = 0;
263                 ByteArray temp;
264
265                 do {
266                         ret = readBinary(sfi, offset, length - offset, temp);
267                         if (ret >= SCARD_ERROR_OK) {
268                                 result += temp;
269                                 offset += temp.size();
270                         }
271                 } while (ret >= SCARD_ERROR_OK && offset < length);
272
273                 return ret;
274         }
275
276         int FileObject::writeBinary(unsigned int sfi, const ByteArray &data, unsigned int offset, unsigned int length)
277         {
278                 ByteArray command, response;
279                 APDUCommand apdu;
280                 int ret;
281
282                 apdu.setCommand(0, APDUCommand::INS_WRITE_BINARY, offset, 0, data, 0);
283                 apdu.getBuffer(command);
284
285                 ret = channel->transmitSync(command, response);
286                 if (ret == 0 && response.size() >= 2) {
287                         ResponseHelper resp(response);
288
289                         if (resp.getStatus() >= 0) {
290                                 _DBG("response [%d] : %s", response.size(), response.toString().c_str());
291
292                                 ret = SUCCESS;
293                         } else {
294                                 _ERR("status word [ %02X %02X ]", resp.getSW1(), resp.getSW2());
295                         }
296                 } else {
297                         _ERR("select apdu is failed, rv [%d], length [%d]", ret, response.size());
298                 }
299
300                 return ret;
301         }
302
303         int FileObject::writeBinary(unsigned int sfi, const ByteArray &data)
304         {
305                 int result;
306                 size_t offset = 0, len;
307                 ByteArray temp;
308
309                 do {
310                         len = MIN(data.size() - offset, MAX_SINGLE_LEN);
311                         temp.setBuffer(data.getBuffer(offset), len);
312                         result = writeBinary(sfi, temp, offset, len);
313                         if (result >= SCARD_ERROR_OK) {
314                                 offset += len;
315                         }
316                 } while (result >= SCARD_ERROR_OK && offset < data.size());
317
318                 return result;
319         }
320
321         int FileObject::readBinaryAll(unsigned int sfi, ByteArray &result)
322         {
323                 int ret;
324
325                 ret = readBinary(sfi, getFCP()->getFileSize(), result);
326
327                 return ret;
328         }
329
330 } /* namespace smartcard_service_api */