• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 #include <map>
21 #include <string>
22 
23 #include <android-base/logging.h>
24 
25 #include <KeyMintUtils.h>
26 
27 namespace keymint::javacard {
28 using ::aidl::android::hardware::security::keymint::KeyParameterValue;
29 using ::aidl::android::hardware::security::keymint::SecurityLevel;
30 using ::aidl::android::hardware::security::keymint::km_utils::kmParam2Aidl;
31 using ::aidl::android::hardware::security::keymint::km_utils::legacy_enum_conversion;
32 using ::aidl::android::hardware::security::keymint::km_utils::typeFromTag;
33 
34 constexpr int SB_ENFORCED = 0;
35 constexpr int TEE_ENFORCED = 1;
36 constexpr int SW_ENFORCED = 2;
37 
38 namespace {
39 
40 template <KeyParameterValue::Tag aidl_tag>
aidlEnumVal2Uint32(const KeyParameterValue & value)41 std::optional<uint32_t> aidlEnumVal2Uint32(const KeyParameterValue& value) {
42     return (value.getTag() == aidl_tag)
43                ? std::optional(static_cast<uint32_t>(value.get<aidl_tag>()))
44                : std::nullopt;
45 }
46 
aidlEnumParam2Uint32(const KeyParameter & param)47 std::optional<uint32_t> aidlEnumParam2Uint32(const KeyParameter& param) {
48     auto tag = legacy_enum_conversion(param.tag);
49     switch (tag) {
50     case KM_TAG_PURPOSE:
51         return aidlEnumVal2Uint32<KeyParameterValue::keyPurpose>(param.value);
52     case KM_TAG_ALGORITHM:
53         return aidlEnumVal2Uint32<KeyParameterValue::algorithm>(param.value);
54     case KM_TAG_BLOCK_MODE:
55         return aidlEnumVal2Uint32<KeyParameterValue::blockMode>(param.value);
56     case KM_TAG_DIGEST:
57     case KM_TAG_RSA_OAEP_MGF_DIGEST:
58         return aidlEnumVal2Uint32<KeyParameterValue::digest>(param.value);
59     case KM_TAG_PADDING:
60         return aidlEnumVal2Uint32<KeyParameterValue::paddingMode>(param.value);
61     case KM_TAG_EC_CURVE:
62         return aidlEnumVal2Uint32<KeyParameterValue::ecCurve>(param.value);
63     case KM_TAG_USER_AUTH_TYPE:
64         return aidlEnumVal2Uint32<KeyParameterValue::hardwareAuthenticatorType>(param.value);
65     case KM_TAG_ORIGIN:
66         return aidlEnumVal2Uint32<KeyParameterValue::origin>(param.value);
67     case KM_TAG_BLOB_USAGE_REQUIREMENTS:
68     case KM_TAG_KDF:
69     default:
70         LOG(FATAL) << "Unknown or unused enum tag: Something is broken";
71         return std::nullopt;
72     }
73 }
74 
75 }  // namespace
76 
addAttestationKey(Array & array,const std::optional<AttestationKey> & attestationKey)77 bool CborConverter::addAttestationKey(Array& array,
78                                       const std::optional<AttestationKey>& attestationKey) {
79     if (attestationKey.has_value()) {
80         array.add(Bstr(attestationKey->keyBlob));
81         addKeyparameters(array, attestationKey->attestKeyParams);
82         array.add(Bstr(attestationKey->issuerSubjectName));
83     } else {
84         array.add(std::move(Bstr(vector<uint8_t>(0))));
85         array.add(std::move(Map()));
86         array.add(std::move(Bstr(vector<uint8_t>(0))));
87     }
88     return true;
89 }
90 
addKeyparameters(Array & array,const vector<KeyParameter> & keyParams)91 bool CborConverter::addKeyparameters(Array& array, const vector<KeyParameter>& keyParams) {
92     Map map;
93     std::map<uint32_t, vector<uint8_t>> enum_repetition;
94     std::map<uint32_t, Array> uint_repetition;
95     for (auto& param : keyParams) {
96         auto tag = legacy_enum_conversion(param.tag);
97         switch (typeFromTag(tag)) {
98         case KM_ENUM: {
99             auto paramEnum = aidlEnumParam2Uint32(param);
100             if (paramEnum.has_value()) {
101                 map.add(static_cast<uint32_t>(tag), *paramEnum);
102             }
103             break;
104         }
105         case KM_UINT:
106             if (param.value.getTag() == KeyParameterValue::integer) {
107                 uint32_t intVal = param.value.get<KeyParameterValue::integer>();
108                 map.add(static_cast<uint32_t>(tag), intVal);
109             }
110             break;
111         case KM_UINT_REP:
112             if (param.value.getTag() == KeyParameterValue::integer) {
113                 uint32_t intVal = param.value.get<KeyParameterValue::integer>();
114                 uint_repetition[static_cast<uint32_t>(tag)].add(intVal);
115             }
116             break;
117         case KM_ENUM_REP: {
118             auto paramEnumRep = aidlEnumParam2Uint32(param);
119             if (paramEnumRep.has_value()) {
120                 enum_repetition[static_cast<uint32_t>(tag)].push_back(*paramEnumRep);
121             }
122             break;
123         }
124         case KM_ULONG:
125             if (param.value.getTag() == KeyParameterValue::longInteger) {
126                 uint64_t longVal = param.value.get<KeyParameterValue::longInteger>();
127                 map.add(static_cast<uint32_t>(tag), longVal);
128             }
129             break;
130         case KM_ULONG_REP:
131             if (param.value.getTag() == KeyParameterValue::longInteger) {
132                 uint64_t longVal = param.value.get<KeyParameterValue::longInteger>();
133                 uint_repetition[static_cast<uint32_t>(tag)].add(longVal);
134             }
135             break;
136         case KM_DATE:
137             if (param.value.getTag() == KeyParameterValue::dateTime) {
138                 uint64_t dateVal = param.value.get<KeyParameterValue::dateTime>();
139                 map.add(static_cast<uint32_t>(tag), dateVal);
140             }
141             break;
142         case KM_BOOL:
143             map.add(static_cast<uint32_t>(tag), 1 /* true */);
144             break;
145         case KM_BIGNUM:
146         case KM_BYTES:
147             if (param.value.getTag() == KeyParameterValue::blob) {
148                 const auto& value = param.value.get<KeyParameterValue::blob>();
149                 map.add(static_cast<uint32_t>(tag), value);
150             }
151             break;
152         case KM_INVALID:
153             break;
154         }
155     }
156 
157     for (auto const& [key, val] : enum_repetition) {
158         Bstr bstr(val);
159         map.add(key, std::move(bstr));
160     }
161 
162     for (auto& [key, val] : uint_repetition) {
163         map.add(key, std::move(val));
164     }
165     array.add(std::move(map));
166     return true;
167 }
168 
169 // Array of three maps
170 std::optional<vector<KeyCharacteristics>>
getKeyCharacteristics(const unique_ptr<Item> & item,const uint32_t pos)171 CborConverter::getKeyCharacteristics(const unique_ptr<Item>& item, const uint32_t pos) {
172     vector<KeyCharacteristics> keyCharacteristics;
173     auto arrayItem = getItemAtPos(item, pos);
174     if (!arrayItem || (MajorType::ARRAY != getType(arrayItem.value()))) {
175         return std::nullopt;
176     }
177     KeyCharacteristics swEnf{SecurityLevel::KEYSTORE, {}};
178     KeyCharacteristics teeEnf{SecurityLevel::TRUSTED_ENVIRONMENT, {}};
179     KeyCharacteristics sbEnf{SecurityLevel::STRONGBOX, {}};
180 
181     auto optSbEnf = getKeyParameters(arrayItem.value(), SB_ENFORCED);
182     if (!optSbEnf) {
183         return std::nullopt;
184     }
185     sbEnf.authorizations = std::move(optSbEnf.value());
186     auto optTeeEnf = getKeyParameters(arrayItem.value(), TEE_ENFORCED);
187     if (!optTeeEnf) {
188         return std::nullopt;
189     }
190     teeEnf.authorizations = std::move(optTeeEnf.value());
191     auto optSwEnf = getKeyParameters(arrayItem.value(), SW_ENFORCED);
192     if (!optSwEnf) {
193         return std::nullopt;
194     }
195     swEnf.authorizations = std::move(optSwEnf.value());
196     // VTS will fail if the authorizations list is empty.
197     if (!sbEnf.authorizations.empty()) keyCharacteristics.push_back(std::move(sbEnf));
198     if (!teeEnf.authorizations.empty()) keyCharacteristics.push_back(std::move(teeEnf));
199     if (!swEnf.authorizations.empty()) keyCharacteristics.push_back(std::move(swEnf));
200     return keyCharacteristics;
201 }
202 
getKeyParameter(const std::pair<const std::unique_ptr<Item> &,const std::unique_ptr<Item> &> pair)203 std::optional<std::vector<KeyParameter>> CborConverter::getKeyParameter(
204     const std::pair<const std::unique_ptr<Item>&, const std::unique_ptr<Item>&> pair) {
205     std::vector<KeyParameter> keyParams;
206     keymaster_tag_t key;
207     auto optValue = getUint64(pair.first);
208     if (!optValue) {
209         return std::nullopt;
210     }
211     key = static_cast<keymaster_tag_t>(optValue.value());
212     switch (keymaster_tag_get_type(key)) {
213     case KM_ENUM_REP: {
214         /* ENUM_REP contains values encoded in a Byte string */
215         const Bstr* bstr = pair.second.get()->asBstr();
216         if (bstr == nullptr) {
217             return std::nullopt;
218         }
219         for (auto bchar : bstr->value()) {
220             keymaster_key_param_t keyParam;
221             keyParam.tag = key;
222             keyParam.enumerated = bchar;
223             keyParams.push_back(kmParam2Aidl(keyParam));
224         }
225         return keyParams;
226     }
227     case KM_ENUM: {
228         keymaster_key_param_t keyParam;
229         keyParam.tag = key;
230         if (!(optValue = getUint64(pair.second))) {
231             return std::nullopt;
232         }
233         keyParam.enumerated = static_cast<uint32_t>(optValue.value());
234         keyParams.push_back(kmParam2Aidl(keyParam));
235         return keyParams;
236     }
237     case KM_UINT: {
238         keymaster_key_param_t keyParam;
239         keyParam.tag = key;
240         if (!(optValue = getUint64(pair.second))) {
241             return std::nullopt;
242         }
243         keyParam.integer = static_cast<uint32_t>(optValue.value());
244         keyParams.push_back(kmParam2Aidl(keyParam));
245         return keyParams;
246     }
247     case KM_ULONG: {
248         keymaster_key_param_t keyParam;
249         keyParam.tag = key;
250         if (!(optValue = getUint64(pair.second))) {
251             return std::nullopt;
252         }
253         keyParam.long_integer = optValue.value();
254         keyParams.push_back(kmParam2Aidl(keyParam));
255         return keyParams;
256     }
257     case KM_UINT_REP: {
258         /* UINT_REP contains values encoded in a Array */
259         Array* array = const_cast<Array*>(pair.second.get()->asArray());
260         if (array == nullptr) return std::nullopt;
261         for (int i = 0; i < array->size(); i++) {
262             keymaster_key_param_t keyParam;
263             keyParam.tag = key;
264             const std::unique_ptr<Item>& item = array->get(i);
265             if (!(optValue = getUint64(item))) {
266                 return std::nullopt;
267             }
268             keyParam.integer = static_cast<uint32_t>(optValue.value());
269             keyParams.push_back(kmParam2Aidl(keyParam));
270         }
271         return keyParams;
272     }
273     case KM_ULONG_REP: {
274         /* ULONG_REP contains values encoded in a Array */
275         Array* array = const_cast<Array*>(pair.second.get()->asArray());
276         if (array == nullptr) return std::nullopt;
277         for (int i = 0; i < array->size(); i++) {
278             keymaster_key_param_t keyParam;
279             keyParam.tag = key;
280             const std::unique_ptr<Item>& item = array->get(i);
281             if (!(optValue = getUint64(item))) {
282                 return std::nullopt;
283             }
284             keyParam.long_integer = optValue.value();
285             keyParams.push_back(kmParam2Aidl(keyParam));
286         }
287         return keyParams;
288     }
289     case KM_DATE: {
290         keymaster_key_param_t keyParam;
291         keyParam.tag = key;
292         if (!(optValue = getUint64(pair.second))) {
293             return std::nullopt;
294         }
295         keyParam.date_time = optValue.value();
296         keyParams.push_back(kmParam2Aidl(keyParam));
297         return keyParams;
298     }
299     case KM_BOOL: {
300         keymaster_key_param_t keyParam;
301         keyParam.tag = key;
302         if (!(optValue = getUint64(pair.second))) {
303             return std::nullopt;
304         }
305         // If a tag with this type is present, the value is true.  If absent,
306         // false.
307         keyParam.boolean = true;
308         keyParams.push_back(kmParam2Aidl(keyParam));
309         return keyParams;
310     }
311     case KM_BIGNUM:
312     case KM_BYTES: {
313         keymaster_key_param_t keyParam;
314         keyParam.tag = key;
315         const Bstr* bstr = pair.second.get()->asBstr();
316         if (bstr == nullptr) return std::nullopt;
317         keyParam.blob.data = bstr->value().data();
318         keyParam.blob.data_length = bstr->value().size();
319         keyParams.push_back(kmParam2Aidl(keyParam));
320         return keyParams;
321     }
322     case KM_INVALID:
323         break;
324     }
325     return std::nullopt;
326 }
327 
328 // array of a blobs
329 std::optional<vector<Certificate>>
getCertificateChain(const std::unique_ptr<Item> & item,const uint32_t pos)330 CborConverter::getCertificateChain(const std::unique_ptr<Item>& item, const uint32_t pos) {
331     vector<Certificate> certChain;
332     auto arrayItem = getItemAtPos(item, pos);
333     if (!arrayItem || (MajorType::ARRAY != getType(arrayItem.value()))) return std::nullopt;
334 
335     const Array* arr = arrayItem.value().get()->asArray();
336     for (int i = 0; i < arr->size(); i++) {
337         Certificate cert;
338         auto optTemp = getByteArrayVec(arrayItem.value(), i);
339         if (!optTemp) return std::nullopt;
340         cert.encodedCertificate = std::move(optTemp.value());
341         certChain.push_back(std::move(cert));
342     }
343     return certChain;
344 }
345 
getTextStr(const unique_ptr<Item> & item,const uint32_t pos)346 std::optional<string> CborConverter::getTextStr(const unique_ptr<Item>& item, const uint32_t pos) {
347     auto textStrItem = getItemAtPos(item, pos);
348     if (!textStrItem || (MajorType::TSTR != getType(textStrItem.value()))) {
349         return std::nullopt;
350     }
351     const Tstr* tstr = textStrItem.value().get()->asTstr();
352     return tstr->value();
353 }
354 
getByteArrayStr(const unique_ptr<Item> & item,const uint32_t pos)355 std::optional<string> CborConverter::getByteArrayStr(const unique_ptr<Item>& item,
356                                                      const uint32_t pos) {
357     auto optTemp = getByteArrayVec(item, pos);
358     if (!optTemp) {
359         return std::nullopt;
360     }
361     std::string str(optTemp->begin(), optTemp->end());
362     return str;
363 }
364 
getByteArrayVec(const unique_ptr<Item> & item,const uint32_t pos)365 std::optional<std::vector<uint8_t>> CborConverter::getByteArrayVec(const unique_ptr<Item>& item,
366                                                                    const uint32_t pos) {
367     auto strItem = getItemAtPos(item, pos);
368     if (!strItem || (MajorType::BSTR != getType(strItem.value()))) {
369         return std::nullopt;
370     }
371     const Bstr* bstr = strItem.value().get()->asBstr();
372     return bstr->value();
373 }
374 
375 std::optional<SharedSecretParameters>
getSharedSecretParameters(const unique_ptr<Item> & item,const uint32_t pos)376 CborConverter::getSharedSecretParameters(const unique_ptr<Item>& item, const uint32_t pos) {
377     SharedSecretParameters params;
378     // Array [seed, nonce]
379     auto arrayItem = getItemAtPos(item, pos);
380     if (!arrayItem || (MajorType::ARRAY != getType(arrayItem.value()))) {
381         return std::nullopt;
382     }
383     auto optSeed = getByteArrayVec(arrayItem.value(), 0);
384     auto optNonce = getByteArrayVec(arrayItem.value(), 1);
385     if (!optSeed || !optNonce) {
386         return std::nullopt;
387     }
388     params.seed = std::move(optSeed.value());
389     params.nonce = std::move(optNonce.value());
390     return params;
391 }
392 
addSharedSecretParameters(Array & array,const vector<SharedSecretParameters> & params)393 bool CborConverter::addSharedSecretParameters(Array& array,
394                                               const vector<SharedSecretParameters>& params) {
395     Array cborParamsVec;
396     for (auto param : params) {
397         Array cborParam;
398         cborParam.add(Bstr(param.seed));
399         cborParam.add(Bstr(param.nonce));
400         cborParamsVec.add(std::move(cborParam));
401     }
402     array.add(std::move(cborParamsVec));
403     return true;
404 }
405 
addTimeStampToken(Array & array,const TimeStampToken & token)406 bool CborConverter::addTimeStampToken(Array& array, const TimeStampToken& token) {
407     Array vToken;
408     vToken.add(static_cast<uint64_t>(token.challenge));
409     vToken.add(static_cast<uint64_t>(token.timestamp.milliSeconds));
410     vToken.add((std::vector<uint8_t>(token.mac)));
411     array.add(std::move(vToken));
412     return true;
413 }
414 
addHardwareAuthToken(Array & array,const HardwareAuthToken & authToken)415 bool CborConverter::addHardwareAuthToken(Array& array, const HardwareAuthToken& authToken) {
416     Array hwAuthToken;
417     hwAuthToken.add(static_cast<uint64_t>(authToken.challenge));
418     hwAuthToken.add(static_cast<uint64_t>(authToken.userId));
419     hwAuthToken.add(static_cast<uint64_t>(authToken.authenticatorId));
420     hwAuthToken.add(static_cast<uint64_t>(authToken.authenticatorType));
421     hwAuthToken.add(static_cast<uint64_t>(authToken.timestamp.milliSeconds));
422     hwAuthToken.add((std::vector<uint8_t>(authToken.mac)));
423     array.add(std::move(hwAuthToken));
424     return true;
425 }
426 
getTimeStampToken(const unique_ptr<Item> & item,const uint32_t pos)427 std::optional<TimeStampToken> CborConverter::getTimeStampToken(const unique_ptr<Item>& item,
428                                                                const uint32_t pos) {
429     TimeStampToken token;
430     // {challenge, timestamp, Mac}
431     auto optChallenge = getUint64(item, pos);
432     auto optTimestampMillis = getUint64(item, pos + 1);
433     auto optTemp = getByteArrayVec(item, pos + 2);
434     if (!optChallenge || !optTimestampMillis || !optTemp) {
435         return std::nullopt;
436     }
437     token.mac = std::move(optTemp.value());
438     token.challenge = static_cast<long>(std::move(optChallenge.value()));
439     token.timestamp.milliSeconds = static_cast<long>(std::move(optTimestampMillis.value()));
440     return token;
441 }
442 
getArrayItem(const std::unique_ptr<Item> & item,const uint32_t pos)443 std::optional<Array> CborConverter::getArrayItem(const std::unique_ptr<Item>& item,
444                                                  const uint32_t pos) {
445     Array array;
446     auto arrayItem = getItemAtPos(item, pos);
447     if (!arrayItem || (MajorType::ARRAY != getType(arrayItem.value()))) {
448         return std::nullopt;
449     }
450     array = std::move(*(arrayItem.value().get()->asArray()));
451     return array;
452 }
453 
getMapItem(const std::unique_ptr<Item> & item,const uint32_t pos)454 std::optional<Map> CborConverter::getMapItem(const std::unique_ptr<Item>& item,
455                                              const uint32_t pos) {
456     Map map;
457     auto mapItem = getItemAtPos(item, pos);
458     if (!mapItem || (MajorType::MAP != getType(mapItem.value()))) {
459         return std::nullopt;
460     }
461     map = std::move(*(mapItem.value().get()->asMap()));
462     return map;
463 }
464 
getKeyParameters(const unique_ptr<Item> & item,const uint32_t pos)465 std::optional<vector<KeyParameter>> CborConverter::getKeyParameters(const unique_ptr<Item>& item,
466                                                                     const uint32_t pos) {
467     vector<KeyParameter> params;
468     auto mapItem = getItemAtPos(item, pos);
469     if (!mapItem || (MajorType::MAP != getType(mapItem.value()))) return std::nullopt;
470     const Map* map = mapItem.value().get()->asMap();
471     size_t mapSize = map->size();
472     for (int i = 0; i < mapSize; i++) {
473         auto optKeyParams = getKeyParameter((*map)[i]);
474         if (optKeyParams) {
475             params.insert(params.end(), optKeyParams->begin(), optKeyParams->end());
476         } else {
477             return std::nullopt;
478         }
479     }
480     return params;
481 }
482 
483 std::tuple<std::unique_ptr<Item>, keymaster_error_t>
decodeData(const std::vector<uint8_t> & response)484 CborConverter::decodeData(const std::vector<uint8_t>& response) {
485     auto [item, pos, message] = cppbor::parse(response);
486     if (!item || MajorType::ARRAY != getType(item)) {
487         return {nullptr, KM_ERROR_UNKNOWN_ERROR};
488     }
489     auto optErrorCode = getErrorCode(item, 0);
490     if (!optErrorCode) {
491         return {nullptr, KM_ERROR_UNKNOWN_ERROR};
492     }
493     return {std::move(item), optErrorCode.value()};
494 }
495 
496 std::optional<keymaster_error_t>
getErrorCode(const std::unique_ptr<cppbor::Item> & item,const uint32_t pos)497 CborConverter::getErrorCode(const std::unique_ptr<cppbor::Item>& item, const uint32_t pos) {
498     auto optErrorVal = getUint64(item, pos);
499     if (!optErrorVal) {
500         return std::nullopt;
501     }
502     return static_cast<keymaster_error_t>(0 - optErrorVal.value());
503 }
504 
getUint64(const unique_ptr<Item> & item)505 std::optional<uint64_t> CborConverter::getUint64(const unique_ptr<Item>& item) {
506     if ((item == nullptr) || (MajorType::UINT != getType(item))) {
507         return std::nullopt;
508     }
509     const Uint* uintVal = item.get()->asUint();
510     return uintVal->unsignedValue();
511 }
512 
getUint64(const unique_ptr<Item> & item,const uint32_t pos)513 std::optional<uint64_t> CborConverter::getUint64(const unique_ptr<Item>& item, const uint32_t pos) {
514     auto intItem = getItemAtPos(item, pos);
515     if (!intItem) {
516         return std::nullopt;
517     }
518     return getUint64(intItem.value());
519 }
520 
521 }  // namespace keymint::javacard
522