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 
37 #include "CborConverter.h"
38 #include <JavacardKeyMintUtils.h>
39 #include <aidl/android/hardware/security/keymint/IKeyMintDevice.h>
40 #include <cppbor.h>
41 #include <map>
42 #include <memory>
43 #include <string>
44 #include <vector>
45 
46 namespace keymint::javacard {
47 using ::aidl::android::hardware::security::keymint::HardwareAuthenticatorType;
48 using ::aidl::android::hardware::security::keymint::SecurityLevel;
49 using ::aidl::android::hardware::security::keymint::km_utils::aidlKeyParams2Km;
50 using ::aidl::android::hardware::security::keymint::km_utils::kmBlob2vector;
51 using ::aidl::android::hardware::security::keymint::km_utils::kmParam2Aidl;
52 using ::aidl::android::hardware::security::keymint::km_utils::typeFromTag;
53 using std::string;
54 using std::unique_ptr;
55 using std::vector;
56 
addAttestationKey(Array & array,const std::optional<AttestationKey> & attestationKey)57 bool CborConverter::addAttestationKey(Array& array,
58                                       const std::optional<AttestationKey>& attestationKey) {
59     if (attestationKey.has_value()) {
60         array.add(Bstr(attestationKey->keyBlob));
61         addKeyparameters(array, attestationKey->attestKeyParams);
62         array.add(Bstr(attestationKey->issuerSubjectName));
63     } else {
64         array.add(std::move(Bstr(vector<uint8_t>(0))));
65         array.add(std::move(Map()));
66         array.add(std::move(Bstr(vector<uint8_t>(0))));
67     }
68     return true;
69 }
70 
addKeyparameters(Array & array,const vector<KeyParameter> & keyParams)71 bool CborConverter::addKeyparameters(Array& array, const vector<KeyParameter>& keyParams) {
72     keymaster_key_param_set_t paramSet = aidlKeyParams2Km(keyParams);
73     Map map;
74     std::map<uint64_t, vector<uint8_t>> enum_repetition;
75     std::map<uint64_t, Array> uint_repetition;
76     for (size_t i = 0; i < paramSet.length; i++) {
77         const auto& param = paramSet.params[i];
78         switch (typeFromTag(param.tag)) {
79         case KM_ENUM:
80             map.add(static_cast<uint64_t>(param.tag), param.enumerated);
81             break;
82         case KM_UINT:
83             map.add(static_cast<uint64_t>(param.tag), param.integer);
84             break;
85         case KM_UINT_REP:
86             uint_repetition[static_cast<uint64_t>(param.tag)].add(param.integer);
87             break;
88         case KM_ENUM_REP:
89             enum_repetition[static_cast<uint64_t>(param.tag)].push_back(
90                 static_cast<uint8_t>(param.enumerated));
91             break;
92         case KM_ULONG:
93             map.add(static_cast<uint64_t>(param.tag), param.long_integer);
94             break;
95         case KM_ULONG_REP:
96             uint_repetition[static_cast<uint64_t>(param.tag & 0x00000000ffffffff)].add(
97                 param.long_integer);
98             break;
99         case KM_DATE:
100             map.add(static_cast<uint64_t>(param.tag), param.date_time);
101             break;
102         case KM_BOOL:
103             map.add(static_cast<uint64_t>(param.tag), static_cast<uint8_t>(param.boolean));
104             break;
105         case KM_BIGNUM:
106         case KM_BYTES:
107             map.add(static_cast<uint64_t>(param.tag & 0x00000000ffffffff),
108                     kmBlob2vector(param.blob));
109             break;
110         default:
111             /* Invalid skip */
112             break;
113         }
114     }
115     if (0 < enum_repetition.size()) {
116         for (auto const& [key, val] : enum_repetition) {
117             Bstr bstr(val);
118             map.add(key, std::move(bstr));
119         }
120     }
121     if (0 < uint_repetition.size()) {
122         for (auto& [key, val] : uint_repetition) {
123             map.add(key, std::move(val));
124         }
125     }
126     array.add(std::move(map));
127     return true;
128 }
129 
130 // Array of three maps
getKeyCharacteristics(const unique_ptr<Item> & item,const uint32_t pos,vector<KeyCharacteristics> & keyCharacteristics)131 bool CborConverter::getKeyCharacteristics(const unique_ptr<Item>& item, const uint32_t pos,
132                                           vector<KeyCharacteristics>& keyCharacteristics) {
133     unique_ptr<Item> arrayItem(nullptr);
134     getItemAtPos(item, pos, arrayItem);
135     if ((arrayItem == nullptr) || (MajorType::ARRAY != getType(arrayItem))) return false;
136 
137     KeyCharacteristics swEnf{SecurityLevel::KEYSTORE, {}};
138     KeyCharacteristics teeEnf{SecurityLevel::TRUSTED_ENVIRONMENT, {}};
139     KeyCharacteristics sbEnf{SecurityLevel::STRONGBOX, {}};
140 
141     if (!getKeyParameters(arrayItem, 0, sbEnf.authorizations) ||
142         !getKeyParameters(arrayItem, 1, teeEnf.authorizations) ||
143         !getKeyParameters(arrayItem, 2, swEnf.authorizations)) {
144         return false;
145     }
146     // VTS will fail if the authorizations list is empty.
147     if (!sbEnf.authorizations.empty()) keyCharacteristics.push_back(std::move(sbEnf));
148     if (!teeEnf.authorizations.empty()) keyCharacteristics.push_back(std::move(teeEnf));
149     if (!swEnf.authorizations.empty()) keyCharacteristics.push_back(std::move(swEnf));
150     return true;
151 }
152 
getKeyParameter(const std::pair<const unique_ptr<Item> &,const unique_ptr<Item> &> pair,vector<KeyParameter> & keyParams)153 bool CborConverter::getKeyParameter(
154     const std::pair<const unique_ptr<Item>&, const unique_ptr<Item>&> pair,
155     vector<KeyParameter>& keyParams) {
156     uint64_t key;
157     uint64_t value;
158     if (!getUint64(pair.first, key)) {
159         return false;
160     }
161     switch (keymaster_tag_get_type(static_cast<keymaster_tag_t>(key))) {
162     case KM_ENUM_REP: {
163         /* ENUM_REP contains values encoded in a Binary string */
164         const Bstr* bstr = pair.second.get()->asBstr();
165         if (bstr == nullptr) return false;
166         for (auto bchar : bstr->value()) {
167             keymaster_key_param_t keyParam;
168             keyParam.tag = static_cast<keymaster_tag_t>(key);
169             keyParam.enumerated = bchar;
170             keyParams.push_back(kmParam2Aidl(keyParam));
171         }
172     } break;
173     case KM_ENUM: {
174         keymaster_key_param_t keyParam;
175         keyParam.tag = static_cast<keymaster_tag_t>(key);
176         if (!getUint64(pair.second, value)) {
177             return false;
178         }
179         keyParam.enumerated = static_cast<uint32_t>(value);
180         keyParams.push_back(kmParam2Aidl(keyParam));
181     } break;
182     case KM_UINT: {
183         keymaster_key_param_t keyParam;
184         keyParam.tag = static_cast<keymaster_tag_t>(key);
185         if (!getUint64(pair.second, value)) {
186             return false;
187         }
188         keyParam.integer = static_cast<uint32_t>(value);
189         keyParams.push_back(kmParam2Aidl(keyParam));
190     } break;
191     case KM_ULONG: {
192         keymaster_key_param_t keyParam;
193         keyParam.tag = static_cast<keymaster_tag_t>(key);
194         if (!getUint64(pair.second, value)) {
195             return false;
196         }
197         keyParam.long_integer = value;
198         keyParams.push_back(kmParam2Aidl(keyParam));
199     } break;
200     case KM_UINT_REP: {
201         /* UINT_REP contains values encoded in a Array */
202         Array* array = const_cast<Array*>(pair.second.get()->asArray());
203         if (array == nullptr) return false;
204         for (int i = 0; i < array->size(); i++) {
205             keymaster_key_param_t keyParam;
206             keyParam.tag = static_cast<keymaster_tag_t>(key);
207             std::unique_ptr<Item> item = std::move((*array)[i]);
208             if (!getUint64(item, value)) {
209                 return false;
210             }
211             keyParam.integer = static_cast<uint32_t>(value);
212             keyParams.push_back(kmParam2Aidl(keyParam));
213         }
214     } break;
215     case KM_ULONG_REP: {
216         /* ULONG_REP contains values encoded in a Array */
217         Array* array = const_cast<Array*>(pair.second.get()->asArray());
218         if (array == nullptr) return false;
219         for (int i = 0; i < array->size(); i++) {
220             keymaster_key_param_t keyParam;
221             keyParam.tag = static_cast<keymaster_tag_t>(key);
222             std::unique_ptr<Item> item = std::move((*array)[i]);
223             if (!getUint64(item, keyParam.long_integer)) {
224                 return false;
225             }
226             keyParams.push_back(kmParam2Aidl(keyParam));
227         }
228     } break;
229     case KM_DATE: {
230         keymaster_key_param_t keyParam;
231         keyParam.tag = static_cast<keymaster_tag_t>(key);
232         if (!getUint64(pair.second, value)) {
233             return false;
234         }
235         keyParam.date_time = value;
236         keyParams.push_back(kmParam2Aidl(keyParam));
237     } break;
238     case KM_BOOL: {
239         keymaster_key_param_t keyParam;
240         keyParam.tag = static_cast<keymaster_tag_t>(key);
241         if (!getUint64(pair.second, value)) {
242             return false;
243         }
244         // TODO re-check the logic below
245         keyParam.boolean = static_cast<bool>(value);
246         keyParams.push_back(kmParam2Aidl(keyParam));
247     } break;
248     case KM_BYTES: {
249         keymaster_key_param_t keyParam;
250         keyParam.tag = static_cast<keymaster_tag_t>(key);
251         const Bstr* bstr = pair.second.get()->asBstr();
252         if (bstr == nullptr) return false;
253         keyParam.blob.data = bstr->value().data();
254         keyParam.blob.data_length = bstr->value().size();
255         keyParams.push_back(kmParam2Aidl(keyParam));
256     } break;
257     default:
258         /* Invalid - return error */
259         return false;
260         break;
261     }
262     return true;
263 }
264 
265 // array of a blobs
getCertificateChain(const std::unique_ptr<Item> & item,const uint32_t pos,vector<Certificate> & certChain)266 bool CborConverter::getCertificateChain(const std::unique_ptr<Item>& item, const uint32_t pos,
267                                         vector<Certificate>& certChain) {
268     std::unique_ptr<Item> arrayItem(nullptr);
269     getItemAtPos(item, pos, arrayItem);
270     if ((arrayItem == nullptr) || (MajorType::ARRAY != getType(arrayItem))) return false;
271 
272     const Array* arr = arrayItem.get()->asArray();
273     for (int i = 0; i < arr->size(); i++) {
274         Certificate cert;
275         if (!getBinaryArray(arrayItem, i, cert.encodedCertificate)) return false;
276         certChain.push_back(std::move(cert));
277     }
278     return true;
279 }
280 
getMultiBinaryArray(const unique_ptr<Item> & item,const uint32_t pos,vector<vector<uint8_t>> & data)281 bool CborConverter::getMultiBinaryArray(const unique_ptr<Item>& item, const uint32_t pos,
282                                         vector<vector<uint8_t>>& data) {
283     bool ret = false;
284     std::unique_ptr<Item> arrayItem(nullptr);
285 
286     getItemAtPos(item, pos, arrayItem);
287     if ((arrayItem == nullptr) || (MajorType::ARRAY != getType(arrayItem))) return ret;
288     const Array* arr = arrayItem.get()->asArray();
289     size_t arrSize = arr->size();
290     for (int i = 0; i < arrSize; i++) {
291         std::vector<uint8_t> temp;
292         if (!getBinaryArray(arrayItem, i, temp)) return ret;
293         data.push_back(std::move(temp));
294     }
295     ret = true;  // success
296     return ret;
297 }
298 
getBinaryArray(const unique_ptr<Item> & item,const uint32_t pos,string & value)299 bool CborConverter::getBinaryArray(const unique_ptr<Item>& item, const uint32_t pos,
300                                    string& value) {
301     vector<uint8_t> vec;
302     string str;
303     if (!getBinaryArray(item, pos, vec)) {
304         return false;
305     }
306     for (auto ch : vec) {
307         str += ch;
308     }
309     value = str;
310     return true;
311 }
312 
getBinaryArray(const unique_ptr<Item> & item,const uint32_t pos,vector<uint8_t> & value)313 bool CborConverter::getBinaryArray(const unique_ptr<Item>& item, const uint32_t pos,
314                                    vector<uint8_t>& value) {
315     bool ret = false;
316     unique_ptr<Item> strItem(nullptr);
317     getItemAtPos(item, pos, strItem);
318     if ((strItem == nullptr) || (MajorType::BSTR != getType(strItem))) return ret;
319 
320     const Bstr* bstr = strItem.get()->asBstr();
321     for (auto bchar : bstr->value()) {
322         value.push_back(bchar);
323     }
324     ret = true;
325     return ret;
326 }
327 
getSharedSecretParameters(const unique_ptr<Item> & item,const uint32_t pos,SharedSecretParameters & params)328 bool CborConverter::getSharedSecretParameters(const unique_ptr<Item>& item, const uint32_t pos,
329                                               SharedSecretParameters& params) {
330     std::unique_ptr<Item> arrayItem(nullptr);
331     // Array [seed, nonce]
332     getItemAtPos(item, pos, arrayItem);
333     if ((arrayItem == nullptr) || (MajorType::ARRAY != getType(arrayItem)) ||
334         !getBinaryArray(arrayItem, 0, params.seed) || !getBinaryArray(arrayItem, 1, params.nonce)) {
335         return false;
336     }
337     return true;
338 }
339 
addSharedSecretParameters(Array & array,const vector<SharedSecretParameters> & params)340 bool CborConverter::addSharedSecretParameters(Array& array,
341                                               const vector<SharedSecretParameters>& params) {
342     Array cborParamsVec;
343     for (const auto &param : params) {
344         Array cborParam;
345         cborParam.add(Bstr(param.seed));
346         cborParam.add(Bstr(param.nonce));
347         cborParamsVec.add(std::move(cborParam));
348     }
349     array.add(std::move(cborParamsVec));
350     return true;
351 }
352 
addTimeStampToken(Array & array,const TimeStampToken & token)353 bool CborConverter::addTimeStampToken(Array& array, const TimeStampToken& token) {
354     Array vToken;
355     vToken.add(static_cast<uint64_t>(token.challenge));
356     vToken.add(static_cast<uint64_t>(token.timestamp.milliSeconds));
357     vToken.add((std::vector<uint8_t>(token.mac)));
358     array.add(std::move(vToken));
359     return true;
360 }
361 
addHardwareAuthToken(Array & array,const HardwareAuthToken & authToken)362 bool CborConverter::addHardwareAuthToken(Array& array, const HardwareAuthToken& authToken) {
363 
364     Array hwAuthToken;
365     hwAuthToken.add(static_cast<uint64_t>(authToken.challenge));
366     hwAuthToken.add(static_cast<uint64_t>(authToken.userId));
367     hwAuthToken.add(static_cast<uint64_t>(authToken.authenticatorId));
368     hwAuthToken.add(static_cast<uint64_t>(authToken.authenticatorType));
369     hwAuthToken.add(static_cast<uint64_t>(authToken.timestamp.milliSeconds));
370     hwAuthToken.add((std::vector<uint8_t>(authToken.mac)));
371     array.add(std::move(hwAuthToken));
372     return true;
373 }
374 
getHardwareAuthToken(const unique_ptr<Item> & item,const uint32_t pos,HardwareAuthToken & token)375 bool CborConverter::getHardwareAuthToken(const unique_ptr<Item>& item, const uint32_t pos,
376                                          HardwareAuthToken& token) {
377     uint64_t authType;
378     uint64_t challenge;
379     uint64_t userId;
380     uint64_t authenticatorId;
381     uint64_t timestampMillis;
382     // challenge, userId, AuthenticatorId, AuthType, Timestamp, MAC
383     if (!getUint64<uint64_t>(item, pos, challenge) ||
384         !getUint64<uint64_t>(item, pos + 1, userId) ||
385         !getUint64<uint64_t>(item, pos + 2, authenticatorId) ||
386         !getUint64<uint64_t>(item, pos + 3, authType) ||
387         !getUint64<uint64_t>(item, pos + 4, timestampMillis) ||
388         !getBinaryArray(item, pos + 5, token.mac)) {
389         return false;
390     }
391     token.challenge = static_cast<int64_t>(challenge);
392     token.userId = static_cast<int64_t>(userId);
393     token.authenticatorId = static_cast<int64_t>(authenticatorId);
394     token.authenticatorType = static_cast<HardwareAuthenticatorType>(authType);
395     token.timestamp.milliSeconds = static_cast<int64_t>(timestampMillis);
396     return true;
397 }
398 
getTimeStampToken(const unique_ptr<Item> & item,const uint32_t pos,TimeStampToken & token)399 bool CborConverter::getTimeStampToken(const unique_ptr<Item>& item, const uint32_t pos,
400                                       TimeStampToken& token) {
401     // {challenge, timestamp, Mac}
402     uint64_t challenge;
403     uint64_t timestampMillis;
404     if (!getUint64<uint64_t>(item, pos, challenge) ||
405         !getUint64<uint64_t>(item, pos + 1, timestampMillis) ||
406         !getBinaryArray(item, pos + 2, token.mac)) {
407         return false;
408     }
409     token.challenge = static_cast<int64_t>(challenge);
410     token.timestamp.milliSeconds = static_cast<int64_t>(timestampMillis);
411     return true;
412 }
413 
getArrayItem(const std::unique_ptr<Item> & item,const uint32_t pos,Array & array)414 bool CborConverter::getArrayItem(const std::unique_ptr<Item>& item, const uint32_t pos,
415                              Array& array) {
416     unique_ptr<Item> arrayItem(nullptr);
417     getItemAtPos(item, pos, arrayItem);
418     if ((arrayItem == nullptr) || (MajorType::ARRAY != getType(arrayItem))) return false;
419     array = std::move(*arrayItem.get()->asArray());
420     return true;
421 }
422 
getMapItem(const std::unique_ptr<Item> & item,const uint32_t pos,Map & map)423 bool CborConverter::getMapItem(const std::unique_ptr<Item>& item, const uint32_t pos,
424                              Map& map) {
425     unique_ptr<Item> mapItem(nullptr);
426     getItemAtPos(item, pos, mapItem);
427     if ((mapItem == nullptr) || (MajorType::MAP != getType(mapItem))) return false;
428     map = std::move(*mapItem.get()->asMap());
429     return true;
430 }
431 
getKeyParameters(const unique_ptr<Item> & item,const uint32_t pos,vector<KeyParameter> & keyParams)432 bool CborConverter::getKeyParameters(const unique_ptr<Item>& item, const uint32_t pos,
433                                      vector<KeyParameter>& keyParams) {
434     bool ret = false;
435     unique_ptr<Item> mapItem(nullptr);
436     vector<KeyParameter> params;
437     getItemAtPos(item, pos, mapItem);
438     if ((mapItem == nullptr) || (MajorType::MAP != getType(mapItem))) return ret;
439     const Map* map = mapItem.get()->asMap();
440     size_t mapSize = map->size();
441     for (int i = 0; i < mapSize; i++) {
442         if (!getKeyParameter((*map)[i], params)) {
443             return ret;
444         }
445     }
446     keyParams.resize(params.size());
447     keyParams = params;
448     ret = true;
449     return ret;
450 }
451 
452 std::tuple<std::unique_ptr<Item>, keymaster_error_t>
decodeData(const std::vector<uint8_t> & response)453 CborConverter::decodeData(const std::vector<uint8_t>& response) {
454     keymaster_error_t errorCode = KM_ERROR_OK;
455     auto [item, pos, message] = parse(response);
456     if (!item || MajorType::ARRAY != getType(item) || !getErrorCode(item, 0, errorCode)) {
457         return {nullptr, KM_ERROR_UNKNOWN_ERROR};
458     }
459     return {std::move(item), errorCode};
460 }
461 
462 }  // namespace keymint::javacard
463