1 /*
2  **
3  ** Copyright 2020, The Android Open Source Project
4  **
5  ** Licensed under the Apache License, Version 2.0 (the "License");
6  ** you may not use this file except in compliance with the License.
7  ** You may obtain a copy of the License at
8  **
9  **     http://www.apache.org/licenses/LICENSE-2.0
10  **
11  ** Unless required by applicable law or agreed to in writing, software
12  ** distributed under the License is distributed on an "AS IS" BASIS,
13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  ** See the License for the specific language governing permissions and
15  ** limitations under the License.
16  */
17 /******************************************************************************
18  *
19  *  The original Work has been changed by NXP.
20  *
21  *  Licensed under the Apache License, Version 2.0 (the "License");
22  *  you may not use this file except in compliance with the License.
23  *  You may obtain a copy of the License at
24  *
25  *  http://www.apache.org/licenses/LICENSE-2.0
26  *
27  *  Unless required by applicable law or agreed to in writing, software
28  *  distributed under the License is distributed on an "AS IS" BASIS,
29  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
30  *  See the License for the specific language governing permissions and
31  *  limitations under the License.
32  *
33  *  Copyright 2023 NXP
34  *
35  ******************************************************************************/
36 #pragma once
37 #include <aidl/android/hardware/security/keymint/Certificate.h>
38 #include <aidl/android/hardware/security/keymint/IKeyMintDevice.h>
39 #include <aidl/android/hardware/security/secureclock/TimeStampToken.h>
40 #include <aidl/android/hardware/security/sharedsecret/ISharedSecret.h>
41 #include <cppbor.h>
42 #include <cppbor_parse.h>
43 #include <iostream>
44 #include <keymaster/android_keymaster_messages.h>
45 #include <memory>
46 #include <numeric>
47 #include <vector>
48 
49 namespace keymint::javacard {
50 using aidl::android::hardware::security::keymint::AttestationKey;
51 using aidl::android::hardware::security::keymint::Certificate;
52 using aidl::android::hardware::security::keymint::HardwareAuthToken;
53 using aidl::android::hardware::security::keymint::KeyCharacteristics;
54 using aidl::android::hardware::security::keymint::KeyParameter;
55 using aidl::android::hardware::security::secureclock::TimeStampToken;
56 using aidl::android::hardware::security::sharedsecret::SharedSecretParameters;
57 using cppbor::Array;
58 using cppbor::Bstr;
59 using cppbor::Item;
60 using cppbor::MajorType;
61 using cppbor::Map;
62 using cppbor::Nint;
63 using cppbor::parse;
64 using cppbor::Uint;
65 using std::string;
66 using std::unique_ptr;
67 using std::vector;
68 
69 class CborConverter {
70   public:
71     CborConverter() = default;
72     ~CborConverter() = default;
73     std::tuple<std::unique_ptr<Item>, keymaster_error_t>
74     decodeData(const std::vector<uint8_t>& response);
75 
76     template <typename T>
77     bool getUint64(const std::unique_ptr<Item>& item, const uint32_t pos, T& value);
78 
79     template <typename T> bool getUint64(const std::unique_ptr<Item>& item, T& value);
80 
81     bool getSharedSecretParameters(const std::unique_ptr<Item>& item, const uint32_t pos,
82                                    SharedSecretParameters& params);
83     bool getBinaryArray(const std::unique_ptr<Item>& item, const uint32_t pos, string& value);
84 
85     bool getBinaryArray(const std::unique_ptr<Item>& item, const uint32_t pos,
86                         vector<uint8_t>& value);
87 
88     bool getHardwareAuthToken(const std::unique_ptr<Item>& item, const uint32_t pos,
89                               HardwareAuthToken& authType);
90 
91     bool getKeyParameters(const std::unique_ptr<Item>& item, const uint32_t pos,
92                           vector<KeyParameter>& keyParams);
93 
94     bool addKeyparameters(Array& array, const vector<KeyParameter>& keyParams);
95 
96     bool addAttestationKey(Array& array, const std::optional<AttestationKey>& attestationKey);
97 
98     bool addHardwareAuthToken(Array& array, const HardwareAuthToken& authToken);
99 
100     bool addSharedSecretParameters(Array& array, const vector<SharedSecretParameters>& params);
101 
102     bool getTimeStampToken(const std::unique_ptr<Item>& item, const uint32_t pos,
103                            TimeStampToken& token);
104 
105     bool getKeyCharacteristics(const std::unique_ptr<Item>& item, const uint32_t pos,
106                                vector<KeyCharacteristics>& keyCharacteristics);
107 
108     bool getCertificateChain(const std::unique_ptr<Item>& item, const uint32_t pos,
109                              vector<Certificate>& keyCharacteristics);
110 
111     bool getMultiBinaryArray(const std::unique_ptr<Item>& item, const uint32_t pos,
112                              vector<vector<uint8_t>>& data);
113 
114     bool addTimeStampToken(Array& array, const TimeStampToken& token);
115 
116     bool getMapItem(const std::unique_ptr<Item>& item, const uint32_t pos,
117                              Map& map);
118 
119     bool getArrayItem(const std::unique_ptr<Item>& item, const uint32_t pos,
120                              Array& array);
121 
getErrorCode(const std::unique_ptr<Item> & item,const uint32_t pos,keymaster_error_t & errorCode)122     inline bool getErrorCode(const std::unique_ptr<Item>& item, const uint32_t pos,
123                              keymaster_error_t& errorCode) {
124         uint64_t errorVal;
125         if (!getUint64<uint64_t>(item, pos, errorVal)) {
126             return false;
127         }
128         errorCode = static_cast<keymaster_error_t>(0 - errorVal);
129         return true;
130     }
131 
132   private:
133     /**
134      * Returns the negative value of the same number.
135      */
get2sCompliment(uint32_t value)136     inline int32_t get2sCompliment(uint32_t value) { return static_cast<int32_t>(~value + 1); }
137 
138     /**
139      * Get the type of the Item pointer.
140      */
getType(const unique_ptr<Item> & item)141     inline MajorType getType(const unique_ptr<Item>& item) { return item.get()->type(); }
142 
143     /**
144      * Construct Keyparameter structure from the pair of key and value. If TagType is  ENUM_REP the
145      * value contains binary string. If TagType is UINT_REP or ULONG_REP the value contains Array of
146      * unsigned integers.
147      */
148     bool getKeyParameter(const std::pair<const unique_ptr<Item>&, const unique_ptr<Item>&> pair,
149                          vector<KeyParameter>& keyParam);
150 
151     /**
152      * Get the sub item pointer from the root item pointer at the given position.
153      */
getItemAtPos(const unique_ptr<Item> & item,const uint32_t pos,unique_ptr<Item> & subItem)154     inline void getItemAtPos(const unique_ptr<Item>& item, const uint32_t pos,
155                              unique_ptr<Item>& subItem) {
156         Array* arr = nullptr;
157 
158         if (MajorType::ARRAY != getType(item)) {
159             return;
160         }
161         arr = const_cast<Array*>(item.get()->asArray());
162         if (arr->size() < (pos + 1)) {
163             return;
164         }
165         subItem = std::move((*arr)[pos]);
166     }
167 };
168 
getUint64(const unique_ptr<Item> & item,T & value)169 template <typename T> bool CborConverter::getUint64(const unique_ptr<Item>& item, T& value) {
170     bool ret = false;
171     if ((item == nullptr) || (std::is_unsigned<T>::value && (MajorType::UINT != getType(item))) ||
172         ((std::is_signed<T>::value && (MajorType::NINT != getType(item))))) {
173         return ret;
174     }
175 
176     if (std::is_unsigned<T>::value) {
177         const Uint* uintVal = item.get()->asUint();
178         value = static_cast<T>(uintVal->value());
179     } else {
180         const Nint* nintVal = item.get()->asNint();
181         value = static_cast<T>(nintVal->value());
182     }
183     ret = true;
184     return ret;  // success
185 }
186 
187 template <typename T>
getUint64(const unique_ptr<Item> & item,const uint32_t pos,T & value)188 bool CborConverter::getUint64(const unique_ptr<Item>& item, const uint32_t pos, T& value) {
189     unique_ptr<Item> intItem(nullptr);
190     getItemAtPos(item, pos, intItem);
191     return getUint64(intItem, value);
192 }
193 }  // namespace keymint::javacard
194