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 qualification */
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 unsigned char ResponseHelper::getSW1()
173 unsigned char ResponseHelper::getSW2()
178 ByteArray ResponseHelper::getDataField()
183 ByteArray ResponseHelper::getDataField(const ByteArray &response)
187 if (response.getLength() > 2)
189 result.setBuffer(response.getBuffer(), response.getLength() - 2);
195 /* APDUCommand class */
196 APDUCommand::APDUCommand()
199 isExtendedLength = false;
200 memset(&header, 0, sizeof(header));
203 APDUCommand::~APDUCommand()
207 bool APDUCommand::setCommand(unsigned char cla, unsigned char ins, unsigned char p1, unsigned char p2, ByteArray commandData, unsigned int maxResponseSize)
213 setCommandData(commandData);
214 setMaxResponseSize(maxResponseSize);
219 bool APDUCommand::setCommand(const ByteArray &command)
223 uint32_t lengthSize = 1;
225 if (command.getLength() < sizeof(header))
230 memcpy(&header, command.getBuffer(offset), sizeof(header));
231 offset += sizeof(header);
233 if (isExtendedLength)
238 if (command.getLength() - offset > lengthSize)
240 unsigned int length = 0;
243 if (isExtendedLength)
250 length = command.getAt(offset);
254 setCommandData(ByteArray(command.getBuffer(offset), length));
258 if (command.getLength() - offset == lengthSize)
260 if (isExtendedLength)
267 setMaxResponseSize(command.getAt(offset));
272 if (command.getLength() == offset)
278 SCARD_DEBUG_ERR("command stream is not correct, command.getLength() [%d], offset [%d]", command.getLength(), offset);
284 bool APDUCommand::setChannel(int type, int channelNum)
290 /* don't apply channel number to below command */
293 case INS_TERMINAL_PROFILE :
296 case INS_TERMINAL_RESPONSE :
300 /* apply channel number */
304 case CLA_CHANNEL_STANDARD : /* standard class byte, two logical channel bits (1~3) */
305 if (channelNum > 0 && channelNum < 4)
311 temp |= (channelNum & 0x03);
318 case CLA_CHANNEL_EXTENDED : /* extended class byte, four logical channel bits (1~15) */
319 if (channelNum > 0 && channelNum < 16)
325 temp |= (channelNum & 0x0F);
342 void APDUCommand::setCLA(unsigned char cla)
351 unsigned char APDUCommand::getCLA()
356 void APDUCommand::setINS(unsigned char ins)
359 if ((ins & 0xF0) == 0x60 || (ins & 0xF0) == 0x90)
365 unsigned char APDUCommand::getINS()
370 void APDUCommand::setP1(unsigned char p1)
373 header.param[0] = p1;
376 unsigned char APDUCommand::getP1()
378 return header.param[0];
381 void APDUCommand::setP2(unsigned char p2)
384 header.param[1] = p2;
387 unsigned char APDUCommand::getP2()
389 return header.param[1];
392 void APDUCommand::setCommandData(const ByteArray &data)
397 ByteArray APDUCommand::getCommandData()
402 void APDUCommand::setMaxResponseSize(unsigned int maxResponseSize)
404 this->maxResponseSize = maxResponseSize;
407 unsigned int APDUCommand::setMaxResponseSize()
409 return maxResponseSize;
412 bool APDUCommand::getBuffer(ByteArray &array)
414 unsigned char *temp_buffer = NULL;
415 unsigned int temp_len = 0;
416 unsigned char lc[3] = { 0, };
417 unsigned int lc_len = 0;
418 unsigned char le[3] = { 0, };
419 unsigned int le_len = 0;
420 unsigned int offset = 0;
423 temp_len += sizeof(header);
425 /* calculate lc length */
426 if (commandData.getLength() > 0)
428 if (isExtendedLength/*commandData.getLength() > 255*/)
430 lc[1] = (commandData.getLength() >> 8) & 0x000000FF;
431 lc[2] = commandData.getLength() & 0x000000FF;
437 lc[0] = commandData.getLength() & 0x000000FF;
445 /* add command data length */
446 temp_len += commandData.getLength();
448 /* calculate le length */
449 if (maxResponseSize > 0)
451 if (isExtendedLength/*commandData.getLength() > 255*/)
453 if (maxResponseSize < 65536)
455 le[1] = (maxResponseSize >> 8) & 0x000000FF;
456 le[2] = maxResponseSize & 0x000000FF;
460 else if (maxResponseSize == 65536)
467 if (maxResponseSize != 256)
468 le[0] = maxResponseSize & 0x000000FF;
476 temp_buffer = new unsigned char[temp_len];
477 if (temp_buffer == NULL)
483 memcpy(temp_buffer + offset, &header, sizeof(header));
484 offset += sizeof(header);
486 if (commandData.getLength() > 0)
488 memcpy(temp_buffer + offset, &lc, lc_len);
491 memcpy(temp_buffer + offset, commandData.getBuffer(), commandData.getLength());
492 offset += commandData.getLength();
495 if (maxResponseSize > 0)
497 memcpy(temp_buffer + offset, &le, le_len);
501 array.setBuffer(temp_buffer, temp_len);
502 delete []temp_buffer;
507 /* APDUHelper class */
508 ByteArray APDUHelper::generateAPDU(int command, int channel, ByteArray data)
515 case COMMAND_OPEN_LOGICAL_CHANNEL :
516 apdu.setCommand(0, APDUCommand::INS_MANAGE_CHANNEL, 0, 0, ByteArray::EMPTY, 1);
517 apdu.getBuffer(result);
520 case COMMAND_CLOSE_LOGICAL_CHANNEL :
521 apdu.setCommand(0, APDUCommand::INS_MANAGE_CHANNEL, 0x80, channel, ByteArray::EMPTY, 0);
522 apdu.getBuffer(result);
525 case COMMAND_SELECT_BY_ID :
526 apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_BY_ID, APDUCommand::P2_SELECT_GET_FCP, data, 0);
527 apdu.getBuffer(result);
530 case COMMAND_SELECT_PARENT_DF :
531 apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_PARENT_DF, APDUCommand::P2_SELECT_GET_FCP, data, 0);
532 apdu.getBuffer(result);
535 case COMMAND_SELECT_BY_DF_NAME :
536 apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_BY_DF_NAME, APDUCommand::P2_SELECT_GET_FCP, data, 0);
537 apdu.getBuffer(result);
540 case COMMAND_SELECT_BY_PATH :
541 apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_BY_PATH, APDUCommand::P2_SELECT_GET_FCP, data, 0);
542 apdu.getBuffer(result);
545 case COMMAND_SELECT_BY_PATH_FROM_CURRENT_DF :
546 apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_BY_PATH_FROM_CURRENT_DF, APDUCommand::P2_SELECT_GET_FCP, data, 0);
547 apdu.getBuffer(result);
557 } /* namespace smartcard_service_api */