• 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         CHECK(false) << "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<uint64_t, vector<uint8_t>> enum_repetition;
94     std::map<uint64_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<uint64_t>(tag), *paramEnum);
102             }
103             break;
104         }
105         case KM_UINT:
106             if (param.value.getTag() == KeyParameterValue::integer) {
107                 auto intVal = param.value.get<KeyParameterValue::integer>();
108                 map.add(static_cast<uint64_t>(tag), intVal);
109             }
110             break;
111         case KM_UINT_REP:
112             if (param.value.getTag() == KeyParameterValue::integer) {
113                 auto intVal = param.value.get<KeyParameterValue::integer>();
114                 uint_repetition[static_cast<uint64_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<uint64_t>(tag)].push_back(*paramEnumRep);
121             }
122             break;
123         }
124         case KM_ULONG:
125             if (param.value.getTag() == KeyParameterValue::longInteger) {
126                 auto longVal = param.value.get<KeyParameterValue::longInteger>();
127                 map.add(static_cast<uint64_t>(tag), longVal);
128             }
129             break;
130         case KM_ULONG_REP:
131             if (param.value.getTag() == KeyParameterValue::longInteger) {
132                 auto longVal = param.value.get<KeyParameterValue::longInteger>();
133                 uint_repetition[static_cast<uint64_t>(tag & 0x00000000ffffffff)].add(longVal);
134             }
135             break;
136         case KM_DATE:
137             if (param.value.getTag() == KeyParameterValue::dateTime) {
138                 auto dateVal = param.value.get<KeyParameterValue::dateTime>();
139                 map.add(static_cast<uint64_t>(tag), dateVal);
140             }
141             break;
142         case KM_BOOL:
143             map.add(static_cast<uint64_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<uint64_t>(tag & 0x00000000ffffffff), 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, false.
306         keyParam.boolean = true;
307         keyParams.push_back(kmParam2Aidl(keyParam));
308         return keyParams;
309     }
310     case KM_BIGNUM:
311     case KM_BYTES: {
312         keymaster_key_param_t keyParam;
313         keyParam.tag = key;
314         const Bstr* bstr = pair.second.get()->asBstr();
315         if (bstr == nullptr) return std::nullopt;
316         keyParam.blob.data = bstr->value().data();
317         keyParam.blob.data_length = bstr->value().size();
318         keyParams.push_back(kmParam2Aidl(keyParam));
319         return keyParams;
320     }
321     case KM_INVALID:
322         break;
323     }
324     return std::nullopt;
325 }
326 
327 // array of a blobs
328 std::optional<vector<Certificate>>
getCertificateChain(const std::unique_ptr<Item> & item,const uint32_t pos)329 CborConverter::getCertificateChain(const std::unique_ptr<Item>& item, const uint32_t pos) {
330     vector<Certificate> certChain;
331     auto arrayItem = getItemAtPos(item, pos);
332     if (!arrayItem || (MajorType::ARRAY != getType(arrayItem.value()))) return std::nullopt;
333 
334     const Array* arr = arrayItem.value().get()->asArray();
335     for (int i = 0; i < arr->size(); i++) {
336         Certificate cert;
337         auto optTemp = getByteArrayVec(arrayItem.value(), i);
338         if (!optTemp) return std::nullopt;
339         cert.encodedCertificate = std::move(optTemp.value());
340         certChain.push_back(std::move(cert));
341     }
342     return certChain;
343 }
344 
getTextStr(const unique_ptr<Item> & item,const uint32_t pos)345 std::optional<string> CborConverter::getTextStr(const unique_ptr<Item>& item, const uint32_t pos) {
346     auto textStrItem = getItemAtPos(item, pos);
347     if (!textStrItem || (MajorType::TSTR != getType(textStrItem.value()))) {
348         return std::nullopt;
349     }
350     const Tstr* tstr = textStrItem.value().get()->asTstr();
351     return tstr->value();
352 }
353 
getByteArrayStr(const unique_ptr<Item> & item,const uint32_t pos)354 std::optional<string> CborConverter::getByteArrayStr(const unique_ptr<Item>& item,
355                                                      const uint32_t pos) {
356     auto optTemp = getByteArrayVec(item, pos);
357     if (!optTemp) {
358         return std::nullopt;
359     }
360     std::string str(optTemp->begin(), optTemp->end());
361     return str;
362 }
363 
getByteArrayVec(const unique_ptr<Item> & item,const uint32_t pos)364 std::optional<std::vector<uint8_t>> CborConverter::getByteArrayVec(const unique_ptr<Item>& item,
365                                                                    const uint32_t pos) {
366     auto strItem = getItemAtPos(item, pos);
367     if (!strItem || (MajorType::BSTR != getType(strItem.value()))) {
368         return std::nullopt;
369     }
370     const Bstr* bstr = strItem.value().get()->asBstr();
371     return bstr->value();
372 }
373 
374 std::optional<SharedSecretParameters>
getSharedSecretParameters(const unique_ptr<Item> & item,const uint32_t pos)375 CborConverter::getSharedSecretParameters(const unique_ptr<Item>& item, const uint32_t pos) {
376     SharedSecretParameters params;
377     // Array [seed, nonce]
378     auto arrayItem = getItemAtPos(item, pos);
379     if (!arrayItem || (MajorType::ARRAY != getType(arrayItem.value()))) {
380         return std::nullopt;
381     }
382     auto optSeed = getByteArrayVec(arrayItem.value(), 0);
383     auto optNonce = getByteArrayVec(arrayItem.value(), 1);
384     if (!optSeed || !optNonce) {
385         return std::nullopt;
386     }
387     params.seed = std::move(optSeed.value());
388     params.nonce = std::move(optNonce.value());
389     return params;
390 }
391 
addSharedSecretParameters(Array & array,const vector<SharedSecretParameters> & params)392 bool CborConverter::addSharedSecretParameters(Array& array,
393                                               const vector<SharedSecretParameters>& params) {
394     Array cborParamsVec;
395     for (auto param : params) {
396         Array cborParam;
397         cborParam.add(Bstr(param.seed));
398         cborParam.add(Bstr(param.nonce));
399         cborParamsVec.add(std::move(cborParam));
400     }
401     array.add(std::move(cborParamsVec));
402     return true;
403 }
404 
addTimeStampToken(Array & array,const TimeStampToken & token)405 bool CborConverter::addTimeStampToken(Array& array, const TimeStampToken& token) {
406     Array vToken;
407     vToken.add(static_cast<uint64_t>(token.challenge));
408     vToken.add(static_cast<uint64_t>(token.timestamp.milliSeconds));
409     vToken.add((std::vector<uint8_t>(token.mac)));
410     array.add(std::move(vToken));
411     return true;
412 }
413 
addHardwareAuthToken(Array & array,const HardwareAuthToken & authToken)414 bool CborConverter::addHardwareAuthToken(Array& array, const HardwareAuthToken& authToken) {
415 
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