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 */
20 /* SLP library header */
25 #include "APDUHelper.h"
26 #include "FileObject.h"
27 #include "NumberStream.h"
28 #include "SimpleTLV.h"
29 #include "ISO7816BERTLV.h"
30 #include "AccessCondition.h"
33 #define EXTERN_API __attribute__((visibility("default")))
36 namespace smartcard_service_api
38 static unsigned char aid_aram[] = { 0xA0, 0x00, 0x00, 0x01, 0x51, 0x41, 0x43, 0x4C, 0x00 };
39 static ByteArray AID_ARAM(ARRAY_AND_SIZE(aid_aram));
41 #define GET_DATA_ALL 0
42 #define GET_DATA_SPECIFIC 1
43 #define GET_DATA_REFRESH_TAG 2
44 #define GET_DATA_NEXT 3
46 #define ARAM_TAG_ALL_AR 0x0000FF40
47 #define ARAM_TAG_AR 0x0000FF50
48 #define ARAM_TAG_REFRESH 0x0000DF20
50 #define DO_TAG_AID_REF 0x0000004F
51 #define DO_TAG_AID_REF_DEFAULT 0x000000C0
52 #define DO_TAG_HASH_REF 0x000000C1
53 #define DO_TAG_APDU_AR 0x000000D0
54 #define DO_TAG_NFC_AR 0x000000D1
55 #define DO_TAG_REF 0x000000E1
56 #define DO_TAG_REF_AR 0x000000E2
57 #define DO_TAG_AR 0x000000E3
59 GPARAM::GPARAM(Channel *channel)
66 return FileObject::select(AID_ARAM);
69 static int doTransmit(Channel *channel, const ByteArray &command, ByteArray &response)
76 result = channel->transmitSync(command, resp);
77 if (result == SCARD_ERROR_OK) {
78 result = ResponseHelper::getStatus(resp);
79 if (result >= SCARD_ERROR_OK) {
80 response = ResponseHelper::getDataField(resp);
81 _DBG("response[%d] : %s", response.size(), response.toString().c_str());
83 _ERR("transmit returns error, [%d]", result);
86 _ERR("transmitSync failed, [%d]", result);
94 static int doCommand(Channel *channel, int command, ByteArray &response)
104 helper.setCommand(0x80, 0xCA, 0xFF, 0x40, ByteArray::EMPTY, 0);
107 case GET_DATA_REFRESH_TAG :
108 helper.setCommand(0x80, 0xCA, 0xDF, 0x20, ByteArray::EMPTY, 0);
112 helper.setCommand(0x80, 0xCA, 0xFF, 0x60, ByteArray::EMPTY, 0);
116 helper.getBuffer(cmd);
118 _DBG("command[%d] : %s", cmd.size(), cmd.toString().c_str());
120 result = doTransmit(channel, cmd, response);
127 static int doCommand(Channel *channel, ByteArray &data, ByteArray &response)
133 helper.setCommand(0x80, 0xCA, 0xFF, 0x50, data, 0);
134 helper.getBuffer(cmd);
136 result = doTransmit(channel, cmd, response);
141 int getLengthAndValue(const ByteArray &data, ByteArray &value)
146 if (data.isEmpty() == true) {
150 if (data.at(offset) == 0xFF && data.at(offset + 1) == 0x40) {
154 count = data.at(offset);
163 for (i = 0; i < count; i++) {
164 result = (result << 8) | data.at(offset + i);
173 value.assign(data.getBuffer(offset),
174 MIN((uint32_t)result,
175 data.size() - offset));
184 int GPARAM::getDataAll(ByteArray &data)
191 result = doCommand(channel, GET_DATA_ALL, response);
192 if (result >= SCARD_ERROR_OK) {
195 length = getLengthAndValue(response, data);
197 while (length > (int)data.size()) {
198 result = doCommand(channel, GET_DATA_NEXT, response);
199 if (result >= SCARD_ERROR_OK) {
202 _ERR("generateCommand failed, [%d]", result);
208 _DBG("data[%d] : %s", data.size(), data.toString().c_str());
209 } else if (length == 0) {
210 _INFO("Response-ALL-AR-DO is empty");
213 _ERR("invalid result, %s", response.toString().c_str());
214 result = SCARD_ERROR_UNAVAILABLE;
217 _ERR("doCommand failed, [%d]", result);
225 static int createRefDo(const ByteArray &aid, const ByteArray &hash, ByteArray &refDo)
229 temp = SimpleTLV::encode(DO_TAG_AID_REF, aid);
230 temp += SimpleTLV::encode(DO_TAG_HASH_REF, hash);
232 refDo = SimpleTLV::encode(DO_TAG_REF, temp);
233 _DBG("encoded Ref DO : %s", refDo.toString().c_str());
235 return SCARD_ERROR_OK;
238 int GPARAM::getDataSpecific(const ByteArray &aid, const ByteArray &hash,
242 ByteArray refDo, response;
246 createRefDo(aid, hash, refDo);
248 result = doCommand(channel, refDo, response);
249 if (result >= SCARD_ERROR_OK) {
250 ISO7816BERTLV tlv(response);
252 if (tlv.decodeTLV() == true &&
253 tlv.getTag() == ARAM_TAG_AR) {
254 unsigned int length = tlv.size();
257 data = tlv.getValue();
259 while (length > data.size()) {
260 result = doCommand(channel, GET_DATA_NEXT, response);
261 if (result >= SCARD_ERROR_OK) {
264 _ERR("generateCommand failed, [%d]", result);
269 _DBG("data[%d] : %s", data.size(), data.toString().c_str());
271 _INFO("Response-ALL-AR-DO is empty");
275 _ERR("decodeTLV failed, %s", response.toString().c_str());
276 result = SCARD_ERROR_ILLEGAL_PARAM;
279 _ERR("doCommand failed, [%d]", result);
287 int GPARAM::getDataRefreshTag(ByteArray &tag)
294 result = doCommand(channel, GET_DATA_REFRESH_TAG, response);
295 if (result >= SCARD_ERROR_OK) {
296 ISO7816BERTLV tlv(response);
298 if (tlv.decodeTLV() == true &&
299 tlv.getTag() == ARAM_TAG_REFRESH &&
301 tag = tlv.getValue();
302 result = SCARD_ERROR_OK;
303 _DBG("refreshTag[%d] : %s", tag.size(), tag.toString().c_str());
305 _ERR("decodeTLV failed, %s", response.toString().c_str());
306 result = SCARD_ERROR_ILLEGAL_PARAM;
309 _ERR("generateCommand failed, [%d]", result);
316 } /* namespace smartcard_service_api */