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