2 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 /* standard library header */
21 /* SLP library header */
25 #include "FileObject.h"
26 #include "APDUHelper.h"
28 namespace smartcard_service_api
30 FileObject::FileObject(Channel *channel)
31 : ProviderHelper(channel)
36 FileObject::FileObject(Channel *channel, const ByteArray &selectResponse)
37 : ProviderHelper(channel)
40 setSelectResponse(selectResponse);
43 FileObject::~FileObject()
48 void FileObject::close()
51 selectResponse.clear();
54 bool FileObject::setSelectResponse(const ByteArray &response)
58 if (response.size() >= 2) {
59 ResponseHelper resp(response);
60 selectResponse = response;
62 if (resp.getStatus() >= 0) {
65 fcp.setFCP(resp.getDataField());
67 _DBG("FCP : %s", fcp.toString().c_str());
72 _ERR("status word [ %02X %02X ]",
73 resp.getSW1(), resp.getSW2());
76 _ERR("invalid response");
82 int FileObject::_select(const ByteArray &command)
84 int ret = ERROR_ILLEGAL_STATE;
87 if (channel == NULL || channel->isClosed())
89 _ERR("channel is not open");
96 ret = channel->transmitSync(command, result);
98 ResponseHelper resp(result);
100 ret = resp.getStatus();
102 setSelectResponse(result);
104 _ERR("select apdu is failed, rv [%d], length [%d]",
107 ret = ERROR_ILLEGAL_STATE;
113 int FileObject::select(const ByteArray &aid)
115 int ret = ERROR_ILLEGAL_STATE;
118 /* make apdu command */
119 command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_DF_NAME, 0, aid);
121 ret = _select(command);
126 int FileObject::select(const ByteArray &path, bool fromCurrentDF)
128 int ret = ERROR_ILLEGAL_STATE;
131 /* make apdu command */
132 if (fromCurrentDF == true) {
133 command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_PATH_FROM_CURRENT_DF, 0, path);
135 ByteArray temp(path);
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);
142 command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_PATH, 0, temp);
145 ret = _select(command);
150 int FileObject::select(unsigned int fid)
152 int ret = ERROR_ILLEGAL_STATE;
153 ByteArray command, fidData((unsigned char *)&fid, 2);
155 /* make apdu command */
156 command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_ID, 0, fidData);
158 ret = _select(command);
163 int FileObject::selectParent()
165 int ret = ERROR_ILLEGAL_STATE;
168 /* make apdu command */
169 command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_PARENT_DF, 0, ByteArray::EMPTY);
171 ret = _select(command);
176 const FCI *FileObject::getFCI() const
181 const FCP *FileObject::getFCP() const
186 int FileObject::readRecord(unsigned int sfi, unsigned int recordId, Record &result)
188 ByteArray command, response;
192 apdu.setCommand(0, APDUCommand::INS_READ_RECORD, recordId, 4, ByteArray::EMPTY, APDUCommand::LE_MAX);
193 apdu.getBuffer(command);
195 ret = channel->transmitSync(command, response);
196 if (ret == 0 && response.size() >= 2) {
197 ResponseHelper resp(response);
199 ret = resp.getStatus();
201 _DBG("response [%d] : %s", response.size(), response.toString().c_str());
203 result = Record(recordId, resp.getDataField());
205 _ERR("status word [ %02X %02X ]", resp.getSW1(), resp.getSW2());
208 _ERR("select apdu is failed, rv [%d], length [%d]", ret, response.size());
214 int FileObject::writeRecord(unsigned int sfi, const Record &record)
219 int FileObject::searchRecord(unsigned int sfi, const ByteArray &searchParam, vector<int> &result)
224 #define MAX_SINGLE_LEN 256
226 int FileObject::readBinary(unsigned int sfi, unsigned int offset, unsigned int length, ByteArray &result)
228 ByteArray command, response;
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);
237 apdu.getBuffer(command);
239 ret = channel->transmitSync(command, response);
240 if (ret == 0 && response.size() >= 2) {
241 ResponseHelper resp(response);
243 if (resp.getStatus() >= 0) {
244 _DBG("response [%d] : %s", response.size(), response.toString().c_str());
246 result = resp.getDataField();
250 _ERR("status word [ %02X %02X ]", resp.getSW1(), resp.getSW2());
253 _ERR("select apdu is failed, rv [%d], length [%d]", ret, response.size());
259 int FileObject::readBinary(unsigned int sfi, unsigned int length, ByteArray &result)
266 ret = readBinary(sfi, offset, length - offset, temp);
267 if (ret >= SCARD_ERROR_OK) {
269 offset += temp.size();
271 } while (ret >= SCARD_ERROR_OK && offset < length);
276 int FileObject::writeBinary(unsigned int sfi, const ByteArray &data, unsigned int offset, unsigned int length)
278 ByteArray command, response;
282 apdu.setCommand(0, APDUCommand::INS_WRITE_BINARY, offset, 0, data, 0);
283 apdu.getBuffer(command);
285 ret = channel->transmitSync(command, response);
286 if (ret == 0 && response.size() >= 2) {
287 ResponseHelper resp(response);
289 if (resp.getStatus() >= 0) {
290 _DBG("response [%d] : %s", response.size(), response.toString().c_str());
294 _ERR("status word [ %02X %02X ]", resp.getSW1(), resp.getSW2());
297 _ERR("select apdu is failed, rv [%d], length [%d]", ret, response.size());
303 int FileObject::writeBinary(unsigned int sfi, const ByteArray &data)
306 size_t offset = 0, len;
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) {
316 } while (result >= SCARD_ERROR_OK && offset < data.size());
321 int FileObject::readBinaryAll(unsigned int sfi, ByteArray &result)
325 ret = readBinary(sfi, getFCP()->getFileSize(), result);
330 } /* namespace smartcard_service_api */