2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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.
18 /* standard library header */
22 /* SLP library header */
26 #include "APDUHelper.h"
28 namespace smartcard_service_api
30 /* ResponseHelper class */
31 ResponseHelper::ResponseHelper()
35 ResponseHelper::ResponseHelper(const ByteArray &response)
37 setResponse(response);
40 ResponseHelper::~ResponseHelper()
44 bool ResponseHelper::setResponse(const ByteArray &response)
48 dataField.releaseBuffer();
50 this->response = response;
52 if (response.getLength() >= 2)
54 sw[0] = response.getReverseAt(1);
55 sw[1] = response.getReverseAt(0);
57 status = parseStatusWord(sw);
59 if (response.getLength() > 2)
61 dataField.setBuffer(response.getBuffer(), response.getLength() - 2);
70 int ResponseHelper::parseStatusWord(unsigned char *sw)
76 /* Normal processing */
77 case (unsigned char)0x90 : /* SW2:00, No further qulification */
80 case (unsigned char)0x91 : /* extra information */
83 case (unsigned char)0x61 : /* SW2 encodes the number of data bytes still available */
86 /* Warning processing */
87 case (unsigned char)0x62 : /* State of non-volatile memory is unchanged (further qualification in SW2) */
90 case (unsigned char)0x63 : /* State of non-volatile memory has changed (further qualification in SW2) */
94 case (unsigned char)0x64 : /* State of non-volatile memory is unchanged (further qualification in SW2) */
98 case (unsigned char)0x65 : /* State of non-volatile memory has changed (further qualification in SW2) */
102 case (unsigned char)0x66 : /* Security-related issues */
107 case (unsigned char)0x67 : /* SW2:00, Wrong length; no further indication */
111 case (unsigned char)0x68 : /* Functions in CLA not supported (further qualification in SW2) */
115 case (unsigned char)0x69 : /* Command not allowed (further qualification in SW2) */
119 case (unsigned char)0x6A : /* Wrong parameters P1-P2 (further qualification in SW2) */
123 case (unsigned char)0x6B : /* SW2:00, Wrong parameters P1-P2 */
127 case (unsigned char)0x6C : /* Wrong Le field; SW2 encodes the exact number of available data bytes */
131 case (unsigned char)0x6D : /* SW2:00, Instruction code not supported or invalid */
135 case (unsigned char)0x6E : /* SW2:00, Class not supported */
139 case (unsigned char)0x6F : /* SW2:00, No precise diagnosis */
151 int ResponseHelper::getStatus()
156 int ResponseHelper::getStatus(const ByteArray &response)
160 if (response.getLength() >= 2)
162 status = ResponseHelper::parseStatusWord(response.getBuffer((response.getLength() - 2)));
168 ByteArray ResponseHelper::getDataField()
173 ByteArray ResponseHelper::getDataField(const ByteArray &response)
177 if (response.getLength() > 2)
179 result.setBuffer(response.getBuffer(), response.getLength() - 2);
185 /* APDUCommand class */
186 APDUCommand::APDUCommand()
189 isExtendedLength = false;
190 memset(&header, 0, sizeof(header));
193 APDUCommand::~APDUCommand()
197 bool APDUCommand::setCommand(unsigned char cla, unsigned char ins, unsigned char p1, unsigned char p2, ByteArray commandData, unsigned int maxResponseSize)
203 setCommandData(commandData);
204 setMaxResponseSize(maxResponseSize);
209 bool APDUCommand::setCommand(const ByteArray &command)
213 uint32_t lengthSize = 1;
215 if (command.getLength() < sizeof(header))
220 memcpy(&header, command.getBuffer(offset), sizeof(header));
221 offset += sizeof(header);
223 if (isExtendedLength)
228 if (command.getLength() - offset > lengthSize)
230 unsigned int length = 0;
233 if (isExtendedLength)
240 length = command.getAt(offset);
244 setCommandData(ByteArray(command.getBuffer(offset), length));
248 if (command.getLength() - offset == lengthSize)
250 if (isExtendedLength)
257 setMaxResponseSize(command.getAt(offset));
262 if (command.getLength() == offset)
268 SCARD_DEBUG_ERR("command stream is not correct, command.getLength() [%d], offset [%d]", command.getLength(), offset);
274 bool APDUCommand::setChannel(int type, int channelNum)
283 if (channelNum > 0 && channelNum < 4)
289 temp |= (channelNum & 0x03);
304 void APDUCommand::setCLA(unsigned char cla)
313 unsigned char APDUCommand::getCLA()
318 void APDUCommand::setINS(unsigned char ins)
321 if ((ins & 0xF0) == 0x60 || (ins & 0xF0) == 0x90)
327 unsigned char APDUCommand::getINS()
332 void APDUCommand::setP1(unsigned char p1)
335 header.param[0] = p1;
338 unsigned char APDUCommand::getP1()
340 return header.param[0];
343 void APDUCommand::setP2(unsigned char p2)
346 header.param[1] = p2;
349 unsigned char APDUCommand::getP2()
351 return header.param[1];
354 void APDUCommand::setCommandData(const ByteArray &data)
359 ByteArray APDUCommand::getCommandData()
364 void APDUCommand::setMaxResponseSize(unsigned int maxResponseSize)
366 this->maxResponseSize = maxResponseSize;
369 unsigned int APDUCommand::setMaxResponseSize()
371 return maxResponseSize;
374 bool APDUCommand::getBuffer(ByteArray &array)
376 unsigned char *temp_buffer = NULL;
377 unsigned int temp_len = 0;
378 unsigned char lc[3] = { 0, };
379 unsigned int lc_len = 0;
380 unsigned char le[3] = { 0, };
381 unsigned int le_len = 0;
382 unsigned int offset = 0;
385 temp_len += sizeof(header);
387 /* calculate lc length */
388 if (commandData.getLength() > 0)
390 if (isExtendedLength/*commandData.getLength() > 255*/)
392 lc[1] = (commandData.getLength() >> 8) & 0x000000FF;
393 lc[2] = commandData.getLength() & 0x000000FF;
399 lc[0] = commandData.getLength() & 0x000000FF;
407 /* add command data length */
408 temp_len += commandData.getLength();
410 /* calculate le length */
411 if (maxResponseSize > 0)
413 if (isExtendedLength/*commandData.getLength() > 255*/)
415 if (maxResponseSize < 65536)
417 le[1] = (maxResponseSize >> 8) & 0x000000FF;
418 le[2] = maxResponseSize & 0x000000FF;
422 else if (maxResponseSize == 65536)
429 if (maxResponseSize != 256)
430 le[0] = maxResponseSize & 0x000000FF;
438 temp_buffer = new unsigned char[temp_len];
439 if (temp_buffer == NULL)
445 memcpy(temp_buffer + offset, &header, sizeof(header));
446 offset += sizeof(header);
448 if (commandData.getLength() > 0)
450 memcpy(temp_buffer + offset, &lc, lc_len);
453 memcpy(temp_buffer + offset, commandData.getBuffer(), commandData.getLength());
454 offset += commandData.getLength();
457 if (maxResponseSize > 0)
459 memcpy(temp_buffer + offset, &le, le_len);
463 array.setBuffer(temp_buffer, temp_len);
464 delete []temp_buffer;
469 /* APDUHelper class */
470 ByteArray APDUHelper::generateAPDU(int command, int channel, ByteArray data)
477 case COMMAND_OPEN_LOGICAL_CHANNEL :
478 apdu.setCommand(0, APDUCommand::INS_MANAGE_CHANNEL, 0, 0, ByteArray::EMPTY, 1);
479 apdu.getBuffer(result);
482 case COMMAND_CLOSE_LOGICAL_CHANNEL :
483 apdu.setCommand(0, APDUCommand::INS_MANAGE_CHANNEL, 0x80, channel, ByteArray::EMPTY, 0);
484 apdu.getBuffer(result);
487 case COMMAND_SELECT_BY_ID :
488 apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_BY_ID, APDUCommand::P2_SELECT_GET_FCP, data, 0);
489 apdu.getBuffer(result);
492 case COMMAND_SELECT_PARENT_DF :
493 apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_PARENT_DF, APDUCommand::P2_SELECT_GET_FCP, data, 0);
494 apdu.getBuffer(result);
497 case COMMAND_SELECT_BY_DF_NAME :
498 apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_BY_DF_NAME, APDUCommand::P2_SELECT_GET_FCP, data, 0);
499 apdu.getBuffer(result);
502 case COMMAND_SELECT_BY_PATH :
503 apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_BY_PATH, APDUCommand::P2_SELECT_GET_FCP, data, 0);
504 apdu.getBuffer(result);
507 case COMMAND_SELECT_BY_PATH_FROM_CURRENT_DF :
508 apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_BY_PATH_FROM_CURRENT_DF, APDUCommand::P2_SELECT_GET_FCP, data, 0);
509 apdu.getBuffer(result);
519 } /* namespace smartcard_service_api */