xref: /aosp_15_r20/external/libese/libapdu/include/apdu/apdu.h (revision 5c4dab75aa57366379dce576b1a9e082a44e2b3a)
1*5c4dab75SAndroid Build Coastguard Worker /*
2*5c4dab75SAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*5c4dab75SAndroid Build Coastguard Worker  *
4*5c4dab75SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*5c4dab75SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*5c4dab75SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*5c4dab75SAndroid Build Coastguard Worker  *
8*5c4dab75SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*5c4dab75SAndroid Build Coastguard Worker  *
10*5c4dab75SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*5c4dab75SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*5c4dab75SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5c4dab75SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*5c4dab75SAndroid Build Coastguard Worker  * limitations under the License.
15*5c4dab75SAndroid Build Coastguard Worker  */
16*5c4dab75SAndroid Build Coastguard Worker 
17*5c4dab75SAndroid Build Coastguard Worker #ifndef APDU_H_
18*5c4dab75SAndroid Build Coastguard Worker #define APDU_H_
19*5c4dab75SAndroid Build Coastguard Worker 
20*5c4dab75SAndroid Build Coastguard Worker #include <cstddef>
21*5c4dab75SAndroid Build Coastguard Worker #include <cstdint>
22*5c4dab75SAndroid Build Coastguard Worker #include <iterator>
23*5c4dab75SAndroid Build Coastguard Worker #include <vector>
24*5c4dab75SAndroid Build Coastguard Worker 
25*5c4dab75SAndroid Build Coastguard Worker namespace android {
26*5c4dab75SAndroid Build Coastguard Worker 
27*5c4dab75SAndroid Build Coastguard Worker /**
28*5c4dab75SAndroid Build Coastguard Worker  * Helper to build an APDU command. If a data section is needed, it is left empty with dataBegin
29*5c4dab75SAndroid Build Coastguard Worker  * and dataEnd able to return iterators to where the data should be filled in.
30*5c4dab75SAndroid Build Coastguard Worker  *
31*5c4dab75SAndroid Build Coastguard Worker  * The command bytes are stored sequentially in the same manner as std::vector.
32*5c4dab75SAndroid Build Coastguard Worker  */
33*5c4dab75SAndroid Build Coastguard Worker class CommandApdu {
34*5c4dab75SAndroid Build Coastguard Worker public:
CommandApdu(uint8_t cla,uint8_t ins,uint8_t p1,uint8_t p2)35*5c4dab75SAndroid Build Coastguard Worker     CommandApdu(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2)
36*5c4dab75SAndroid Build Coastguard Worker             : CommandApdu(cla, ins, p1, p2, 0, 0) {}
37*5c4dab75SAndroid Build Coastguard Worker     CommandApdu(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, size_t lc, size_t le);
38*5c4dab75SAndroid Build Coastguard Worker 
39*5c4dab75SAndroid Build Coastguard Worker     using iterator = std::vector<uint8_t>::iterator;
40*5c4dab75SAndroid Build Coastguard Worker     using const_iterator = std::vector<uint8_t>::const_iterator;
41*5c4dab75SAndroid Build Coastguard Worker 
begin()42*5c4dab75SAndroid Build Coastguard Worker     iterator begin() { return mCommand.begin(); }
end()43*5c4dab75SAndroid Build Coastguard Worker     iterator end() { return mCommand.end(); }
begin()44*5c4dab75SAndroid Build Coastguard Worker     const_iterator begin() const { return mCommand.begin(); }
end()45*5c4dab75SAndroid Build Coastguard Worker     const_iterator end() const { return mCommand.end(); }
46*5c4dab75SAndroid Build Coastguard Worker 
dataBegin()47*5c4dab75SAndroid Build Coastguard Worker     iterator dataBegin() { return mDataBegin; }
dataEnd()48*5c4dab75SAndroid Build Coastguard Worker     iterator dataEnd() { return mDataEnd; }
dataBegin()49*5c4dab75SAndroid Build Coastguard Worker     const_iterator dataBegin() const { return mDataBegin; }
dataEnd()50*5c4dab75SAndroid Build Coastguard Worker     const_iterator dataEnd() const { return mDataEnd; }
51*5c4dab75SAndroid Build Coastguard Worker 
size()52*5c4dab75SAndroid Build Coastguard Worker     size_t size() const { return mCommand.size(); }
dataSize()53*5c4dab75SAndroid Build Coastguard Worker     size_t dataSize() const { return std::distance(mDataBegin, mDataEnd); }
54*5c4dab75SAndroid Build Coastguard Worker 
vector()55*5c4dab75SAndroid Build Coastguard Worker     const std::vector<uint8_t>& vector() const { return mCommand; }
56*5c4dab75SAndroid Build Coastguard Worker 
57*5c4dab75SAndroid Build Coastguard Worker private:
58*5c4dab75SAndroid Build Coastguard Worker     std::vector<uint8_t> mCommand;
59*5c4dab75SAndroid Build Coastguard Worker     std::vector<uint8_t>::iterator mDataBegin;
60*5c4dab75SAndroid Build Coastguard Worker     std::vector<uint8_t>::iterator mDataEnd;
61*5c4dab75SAndroid Build Coastguard Worker };
62*5c4dab75SAndroid Build Coastguard Worker 
63*5c4dab75SAndroid Build Coastguard Worker /**
64*5c4dab75SAndroid Build Coastguard Worker  * Helper to deconstruct a response APDU. This wraps a reference to an iterable byte container.
65*5c4dab75SAndroid Build Coastguard Worker  */
66*5c4dab75SAndroid Build Coastguard Worker template<typename T>
67*5c4dab75SAndroid Build Coastguard Worker class ResponseApdu {
68*5c4dab75SAndroid Build Coastguard Worker     static constexpr size_t STATUS_SIZE = 2;
69*5c4dab75SAndroid Build Coastguard Worker     static constexpr uint8_t BYTES_AVAILABLE = 0x61;
70*5c4dab75SAndroid Build Coastguard Worker     static constexpr uint8_t SW1_WARNING_NON_VOLATILE_MEMORY_UNCHANGED = 0x62;
71*5c4dab75SAndroid Build Coastguard Worker     static constexpr uint8_t SW1_WARNING_NON_VOLATILE_MEMORY_CHANGED = 0x63;
72*5c4dab75SAndroid Build Coastguard Worker     static constexpr uint8_t SW1_FIRST_EXECUTION_ERROR = 0x64;
73*5c4dab75SAndroid Build Coastguard Worker     static constexpr uint8_t SW1_LAST_EXECUTION_ERROR = 0x66;
74*5c4dab75SAndroid Build Coastguard Worker     static constexpr uint8_t SW1_FIRST_CHECKING_ERROR = 0x67;
75*5c4dab75SAndroid Build Coastguard Worker     static constexpr uint8_t SW1_LAST_CHECKING_ERROR = 0x6f;
76*5c4dab75SAndroid Build Coastguard Worker 
77*5c4dab75SAndroid Build Coastguard Worker public:
ResponseApdu(const T & data)78*5c4dab75SAndroid Build Coastguard Worker     ResponseApdu(const T& data) : mData(data) {}
79*5c4dab75SAndroid Build Coastguard Worker 
ok()80*5c4dab75SAndroid Build Coastguard Worker     bool ok() const {
81*5c4dab75SAndroid Build Coastguard Worker         return static_cast<size_t>(
82*5c4dab75SAndroid Build Coastguard Worker                 std::distance(std::begin(mData), std::end(mData))) >= STATUS_SIZE;
83*5c4dab75SAndroid Build Coastguard Worker     }
84*5c4dab75SAndroid Build Coastguard Worker 
sw1()85*5c4dab75SAndroid Build Coastguard Worker     uint8_t sw1() const { return *(std::end(mData) - 2); }
sw2()86*5c4dab75SAndroid Build Coastguard Worker     uint8_t sw2() const { return *(std::end(mData) - 1); }
status()87*5c4dab75SAndroid Build Coastguard Worker     uint16_t status() const { return (static_cast<uint16_t>(sw1()) << 8) | sw2(); }
88*5c4dab75SAndroid Build Coastguard Worker 
remainingBytes()89*5c4dab75SAndroid Build Coastguard Worker     int8_t remainingBytes() const { return sw1() == BYTES_AVAILABLE ? sw2() : 0; }
90*5c4dab75SAndroid Build Coastguard Worker 
isWarning()91*5c4dab75SAndroid Build Coastguard Worker     bool isWarning() const {
92*5c4dab75SAndroid Build Coastguard Worker         const uint8_t sw1 = this->sw1();
93*5c4dab75SAndroid Build Coastguard Worker         return sw1 == SW1_WARNING_NON_VOLATILE_MEMORY_UNCHANGED
94*5c4dab75SAndroid Build Coastguard Worker             || sw1 == SW1_WARNING_NON_VOLATILE_MEMORY_CHANGED;
95*5c4dab75SAndroid Build Coastguard Worker     }
isExecutionError()96*5c4dab75SAndroid Build Coastguard Worker     bool isExecutionError() const {
97*5c4dab75SAndroid Build Coastguard Worker         const uint8_t sw1 = this->sw1();
98*5c4dab75SAndroid Build Coastguard Worker         return sw1 >= SW1_FIRST_EXECUTION_ERROR && sw1 <= SW1_LAST_EXECUTION_ERROR;
99*5c4dab75SAndroid Build Coastguard Worker     }
isCheckingError()100*5c4dab75SAndroid Build Coastguard Worker     bool isCheckingError() const {
101*5c4dab75SAndroid Build Coastguard Worker         const uint8_t sw1 = this->sw1();
102*5c4dab75SAndroid Build Coastguard Worker         return sw1 >= SW1_FIRST_CHECKING_ERROR && sw1 <= SW1_LAST_CHECKING_ERROR;
103*5c4dab75SAndroid Build Coastguard Worker     }
isError()104*5c4dab75SAndroid Build Coastguard Worker     bool isError() const { return isExecutionError() || isCheckingError(); }
105*5c4dab75SAndroid Build Coastguard Worker 
dataBegin()106*5c4dab75SAndroid Build Coastguard Worker     auto dataBegin() const { return std::begin(mData); }
dataEnd()107*5c4dab75SAndroid Build Coastguard Worker     auto dataEnd() const { return std::end(mData) - STATUS_SIZE; }
108*5c4dab75SAndroid Build Coastguard Worker 
dataSize()109*5c4dab75SAndroid Build Coastguard Worker     size_t dataSize() const { return std::distance(dataBegin(), dataEnd()); }
110*5c4dab75SAndroid Build Coastguard Worker 
111*5c4dab75SAndroid Build Coastguard Worker private:
112*5c4dab75SAndroid Build Coastguard Worker     const T& mData;
113*5c4dab75SAndroid Build Coastguard Worker };
114*5c4dab75SAndroid Build Coastguard Worker 
115*5c4dab75SAndroid Build Coastguard Worker } // namespace android
116*5c4dab75SAndroid Build Coastguard Worker 
117*5c4dab75SAndroid Build Coastguard Worker #endif // APDU_H_
118