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 ¶m : 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