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