1 /* 2 * Copyright (C) 2017 The Android Open Source Project 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 #include <apdu/apdu.h> 18 19 #include <limits> 20 21 namespace android { 22 23 CommandApdu::CommandApdu(const uint8_t cla, const uint8_t ins, const uint8_t p1, const uint8_t p2, 24 const size_t lc, const size_t le) { 25 constexpr size_t headerSize = 4; 26 constexpr size_t shortLcMax = std::numeric_limits<uint8_t>::max(); 27 constexpr size_t shortLeMax = std::numeric_limits<uint8_t>::max() + 1; 28 //constexpr size_t extendedLcMax = std::numeric_limits<uint16_t>::max(); 29 constexpr size_t extendedLeMax = std::numeric_limits<uint16_t>::max() + 1; 30 31 const bool extended = lc > shortLcMax || le > shortLeMax; 32 const bool hasLc = lc > 0; 33 const bool hasLe = le > 0; 34 const size_t lcSize = hasLc ? (extended ? 3 : 1) : 0; 35 const size_t leSize = hasLe ? (extended ? (hasLc ? 2 : 3) : 1) : 0; 36 const size_t commandSize = headerSize + lcSize + lc + leSize; 37 mCommand.resize(commandSize, 0); 38 39 // All cases have the header 40 auto it = mCommand.begin(); 41 *it++ = cla; 42 *it++ = ins; 43 *it++ = p1; 44 *it++ = p2; 45 46 // Cases 3 & 4 send data 47 if (hasLc) { 48 if (extended) { 49 *it++ = 0; 50 *it++ = 0xff & (lc >> 8); 51 } 52 *it++ = 0xff & lc; 53 mDataBegin = it; 54 it += lc; 55 mDataEnd = it; 56 } else { 57 mDataBegin = mDataEnd = mCommand.end(); 58 } 59 60 // Cases 2 & 4 expect data back 61 if (hasLe) { 62 if (extended) { 63 if (!hasLc) { 64 *it++ = 0; 65 } 66 const bool isLeMax = le == extendedLeMax; 67 *it++ = (isLeMax ? 0 : 0xff & (le >> 8)); 68 *it++ = (isLeMax ? 0 : 0xff & le); 69 } else { 70 *it++ = (le == shortLeMax ? 0 : 0xff & le); 71 } 72 } 73 } 74 75 } // namespace android 76