Home | History | Annotate | Download | only in libapdu
      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