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