1 /*
2 * Copyright 2019, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "IdentityCredentialSupport"
18
19 #include <android/hardware/identity/support/IdentityCredentialSupport.h>
20
21 #define _POSIX_C_SOURCE 199309L
22
23 #include <ctype.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <time.h>
27 #include <chrono>
28 #include <iomanip>
29
30 #include <openssl/aes.h>
31 #include <openssl/bn.h>
32 #include <openssl/crypto.h>
33 #include <openssl/ec.h>
34 #include <openssl/err.h>
35 #include <openssl/evp.h>
36 #include <openssl/hkdf.h>
37 #include <openssl/hmac.h>
38 #include <openssl/objects.h>
39 #include <openssl/pem.h>
40 #include <openssl/pkcs12.h>
41 #include <openssl/rand.h>
42 #include <openssl/x509.h>
43 #include <openssl/x509_vfy.h>
44
45 #include <android-base/logging.h>
46 #include <android-base/stringprintf.h>
47
48 #include <cppbor.h>
49 #include <cppbor_parse.h>
50
51 #include <android/hardware/keymaster/4.0/types.h>
52 #include <keymaster/authorization_set.h>
53 #include <keymaster/contexts/pure_soft_keymaster_context.h>
54 #include <keymaster/contexts/soft_attestation_cert.h>
55 #include <keymaster/keymaster_tags.h>
56 #include <keymaster/km_openssl/attestation_utils.h>
57
58 namespace android {
59 namespace hardware {
60 namespace identity {
61 namespace support {
62
63 using ::std::pair;
64 using ::std::unique_ptr;
65
66 // ---------------------------------------------------------------------------
67 // Miscellaneous utilities.
68 // ---------------------------------------------------------------------------
69
hexdump(const string & name,const vector<uint8_t> & data)70 void hexdump(const string& name, const vector<uint8_t>& data) {
71 fprintf(stderr, "%s: dumping %zd bytes\n", name.c_str(), data.size());
72 size_t n, m, o;
73 for (n = 0; n < data.size(); n += 16) {
74 fprintf(stderr, "%04zx ", n);
75 for (m = 0; m < 16 && n + m < data.size(); m++) {
76 fprintf(stderr, "%02x ", data[n + m]);
77 }
78 for (o = m; o < 16; o++) {
79 fprintf(stderr, " ");
80 }
81 fprintf(stderr, " ");
82 for (m = 0; m < 16 && n + m < data.size(); m++) {
83 int c = data[n + m];
84 fprintf(stderr, "%c", isprint(c) ? c : '.');
85 }
86 fprintf(stderr, "\n");
87 }
88 fprintf(stderr, "\n");
89 }
90
encodeHex(const uint8_t * data,size_t dataLen)91 string encodeHex(const uint8_t* data, size_t dataLen) {
92 static const char hexDigits[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
93 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
94
95 string ret;
96 ret.resize(dataLen * 2);
97 for (size_t n = 0; n < dataLen; n++) {
98 uint8_t byte = data[n];
99 ret[n * 2 + 0] = hexDigits[byte >> 4];
100 ret[n * 2 + 1] = hexDigits[byte & 0x0f];
101 }
102
103 return ret;
104 }
105
encodeHex(const string & str)106 string encodeHex(const string& str) {
107 return encodeHex(reinterpret_cast<const uint8_t*>(str.data()), str.size());
108 }
109
encodeHex(const vector<uint8_t> & data)110 string encodeHex(const vector<uint8_t>& data) {
111 return encodeHex(data.data(), data.size());
112 }
113
114 // Returns -1 on error, otherwise an integer in the range 0 through 15, both inclusive.
parseHexDigit(char hexDigit)115 int parseHexDigit(char hexDigit) {
116 if (hexDigit >= '0' && hexDigit <= '9') {
117 return int(hexDigit) - '0';
118 } else if (hexDigit >= 'a' && hexDigit <= 'f') {
119 return int(hexDigit) - 'a' + 10;
120 } else if (hexDigit >= 'A' && hexDigit <= 'F') {
121 return int(hexDigit) - 'A' + 10;
122 }
123 return -1;
124 }
125
decodeHex(const string & hexEncoded)126 optional<vector<uint8_t>> decodeHex(const string& hexEncoded) {
127 vector<uint8_t> out;
128 size_t hexSize = hexEncoded.size();
129 if ((hexSize & 1) != 0) {
130 LOG(ERROR) << "Size of data cannot be odd";
131 return {};
132 }
133
134 out.resize(hexSize / 2);
135 for (size_t n = 0; n < hexSize / 2; n++) {
136 int upperNibble = parseHexDigit(hexEncoded[n * 2]);
137 int lowerNibble = parseHexDigit(hexEncoded[n * 2 + 1]);
138 if (upperNibble == -1 || lowerNibble == -1) {
139 LOG(ERROR) << "Invalid hex digit at position " << n;
140 return {};
141 }
142 out[n] = (upperNibble << 4) + lowerNibble;
143 }
144
145 return out;
146 }
147
148 // ---------------------------------------------------------------------------
149 // CBOR utilities.
150 // ---------------------------------------------------------------------------
151
cborAreAllElementsNonCompound(const cppbor::CompoundItem * compoundItem)152 static bool cborAreAllElementsNonCompound(const cppbor::CompoundItem* compoundItem) {
153 if (compoundItem->type() == cppbor::ARRAY) {
154 const cppbor::Array* array = compoundItem->asArray();
155 for (size_t n = 0; n < array->size(); n++) {
156 const cppbor::Item* entry = (*array)[n].get();
157 switch (entry->type()) {
158 case cppbor::ARRAY:
159 case cppbor::MAP:
160 return false;
161 default:
162 break;
163 }
164 }
165 } else {
166 const cppbor::Map* map = compoundItem->asMap();
167 for (size_t n = 0; n < map->size(); n++) {
168 auto [keyEntry, valueEntry] = (*map)[n];
169 switch (keyEntry->type()) {
170 case cppbor::ARRAY:
171 case cppbor::MAP:
172 return false;
173 default:
174 break;
175 }
176 switch (valueEntry->type()) {
177 case cppbor::ARRAY:
178 case cppbor::MAP:
179 return false;
180 default:
181 break;
182 }
183 }
184 }
185 return true;
186 }
187
cborPrettyPrintInternal(const cppbor::Item * item,string & out,size_t indent,size_t maxBStrSize,const vector<string> & mapKeysToNotPrint)188 static bool cborPrettyPrintInternal(const cppbor::Item* item, string& out, size_t indent,
189 size_t maxBStrSize, const vector<string>& mapKeysToNotPrint) {
190 char buf[80];
191
192 string indentString(indent, ' ');
193
194 switch (item->type()) {
195 case cppbor::UINT:
196 snprintf(buf, sizeof(buf), "%" PRIu64, item->asUint()->unsignedValue());
197 out.append(buf);
198 break;
199
200 case cppbor::NINT:
201 snprintf(buf, sizeof(buf), "%" PRId64, item->asNint()->value());
202 out.append(buf);
203 break;
204
205 case cppbor::BSTR: {
206 const cppbor::Bstr* bstr = item->asBstr();
207 const vector<uint8_t>& value = bstr->value();
208 if (value.size() > maxBStrSize) {
209 unsigned char digest[SHA_DIGEST_LENGTH];
210 SHA_CTX ctx;
211 SHA1_Init(&ctx);
212 SHA1_Update(&ctx, value.data(), value.size());
213 SHA1_Final(digest, &ctx);
214 char buf2[SHA_DIGEST_LENGTH * 2 + 1];
215 for (size_t n = 0; n < SHA_DIGEST_LENGTH; n++) {
216 snprintf(buf2 + n * 2, 3, "%02x", digest[n]);
217 }
218 snprintf(buf, sizeof(buf), "<bstr size=%zd sha1=%s>", value.size(), buf2);
219 out.append(buf);
220 } else {
221 out.append("{");
222 for (size_t n = 0; n < value.size(); n++) {
223 if (n > 0) {
224 out.append(", ");
225 }
226 snprintf(buf, sizeof(buf), "0x%02x", value[n]);
227 out.append(buf);
228 }
229 out.append("}");
230 }
231 } break;
232
233 case cppbor::TSTR:
234 out.append("'");
235 {
236 // TODO: escape "'" characters
237 out.append(item->asTstr()->value().c_str());
238 }
239 out.append("'");
240 break;
241
242 case cppbor::ARRAY: {
243 const cppbor::Array* array = item->asArray();
244 if (array->size() == 0) {
245 out.append("[]");
246 } else if (cborAreAllElementsNonCompound(array)) {
247 out.append("[");
248 for (size_t n = 0; n < array->size(); n++) {
249 if (!cborPrettyPrintInternal((*array)[n].get(), out, indent + 2, maxBStrSize,
250 mapKeysToNotPrint)) {
251 return false;
252 }
253 out.append(", ");
254 }
255 out.append("]");
256 } else {
257 out.append("[\n" + indentString);
258 for (size_t n = 0; n < array->size(); n++) {
259 out.append(" ");
260 if (!cborPrettyPrintInternal((*array)[n].get(), out, indent + 2, maxBStrSize,
261 mapKeysToNotPrint)) {
262 return false;
263 }
264 out.append(",\n" + indentString);
265 }
266 out.append("]");
267 }
268 } break;
269
270 case cppbor::MAP: {
271 const cppbor::Map* map = item->asMap();
272
273 if (map->size() == 0) {
274 out.append("{}");
275 } else {
276 out.append("{\n" + indentString);
277 for (size_t n = 0; n < map->size(); n++) {
278 out.append(" ");
279
280 auto [map_key, map_value] = (*map)[n];
281
282 if (!cborPrettyPrintInternal(map_key.get(), out, indent + 2, maxBStrSize,
283 mapKeysToNotPrint)) {
284 return false;
285 }
286 out.append(" : ");
287 if (map_key->type() == cppbor::TSTR &&
288 std::find(mapKeysToNotPrint.begin(), mapKeysToNotPrint.end(),
289 map_key->asTstr()->value()) != mapKeysToNotPrint.end()) {
290 out.append("<not printed>");
291 } else {
292 if (!cborPrettyPrintInternal(map_value.get(), out, indent + 2, maxBStrSize,
293 mapKeysToNotPrint)) {
294 return false;
295 }
296 }
297 out.append(",\n" + indentString);
298 }
299 out.append("}");
300 }
301 } break;
302
303 case cppbor::SEMANTIC: {
304 const cppbor::Semantic* semantic = item->asSemantic();
305 snprintf(buf, sizeof(buf), "tag %" PRIu64 " ", semantic->value());
306 out.append(buf);
307 cborPrettyPrintInternal(semantic->child().get(), out, indent, maxBStrSize,
308 mapKeysToNotPrint);
309 } break;
310
311 case cppbor::SIMPLE:
312 const cppbor::Bool* asBool = item->asSimple()->asBool();
313 const cppbor::Null* asNull = item->asSimple()->asNull();
314 if (asBool != nullptr) {
315 out.append(asBool->value() ? "true" : "false");
316 } else if (asNull != nullptr) {
317 out.append("null");
318 } else {
319 LOG(ERROR) << "Only boolean/null is implemented for SIMPLE";
320 return false;
321 }
322 break;
323 }
324
325 return true;
326 }
327
cborPrettyPrint(const vector<uint8_t> & encodedCbor,size_t maxBStrSize,const vector<string> & mapKeysToNotPrint)328 string cborPrettyPrint(const vector<uint8_t>& encodedCbor, size_t maxBStrSize,
329 const vector<string>& mapKeysToNotPrint) {
330 auto [item, _, message] = cppbor::parse(encodedCbor);
331 if (item == nullptr) {
332 LOG(ERROR) << "Data to pretty print is not valid CBOR: " << message;
333 return "";
334 }
335
336 string out;
337 cborPrettyPrintInternal(item.get(), out, 0, maxBStrSize, mapKeysToNotPrint);
338 return out;
339 }
340
341 // ---------------------------------------------------------------------------
342 // Crypto functionality / abstraction.
343 // ---------------------------------------------------------------------------
344
345 struct EVP_CIPHER_CTX_Deleter {
operator ()android::hardware::identity::support::EVP_CIPHER_CTX_Deleter346 void operator()(EVP_CIPHER_CTX* ctx) const {
347 if (ctx != nullptr) {
348 EVP_CIPHER_CTX_free(ctx);
349 }
350 }
351 };
352
353 using EvpCipherCtxPtr = unique_ptr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_Deleter>;
354
355 // bool getRandom(size_t numBytes, vector<uint8_t>& output) {
getRandom(size_t numBytes)356 optional<vector<uint8_t>> getRandom(size_t numBytes) {
357 vector<uint8_t> output;
358 output.resize(numBytes);
359 if (RAND_bytes(output.data(), numBytes) != 1) {
360 LOG(ERROR) << "RAND_bytes: failed getting " << numBytes << " random";
361 return {};
362 }
363 return output;
364 }
365
decryptAes128Gcm(const vector<uint8_t> & key,const vector<uint8_t> & encryptedData,const vector<uint8_t> & additionalAuthenticatedData)366 optional<vector<uint8_t>> decryptAes128Gcm(const vector<uint8_t>& key,
367 const vector<uint8_t>& encryptedData,
368 const vector<uint8_t>& additionalAuthenticatedData) {
369 int cipherTextSize = int(encryptedData.size()) - kAesGcmIvSize - kAesGcmTagSize;
370 if (cipherTextSize < 0) {
371 LOG(ERROR) << "encryptedData too small";
372 return {};
373 }
374 unsigned char* nonce = (unsigned char*)encryptedData.data();
375 unsigned char* cipherText = nonce + kAesGcmIvSize;
376 unsigned char* tag = cipherText + cipherTextSize;
377
378 vector<uint8_t> plainText;
379 plainText.resize(cipherTextSize);
380
381 auto ctx = EvpCipherCtxPtr(EVP_CIPHER_CTX_new());
382 if (ctx.get() == nullptr) {
383 LOG(ERROR) << "EVP_CIPHER_CTX_new: failed";
384 return {};
385 }
386
387 if (EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_gcm(), NULL, NULL, NULL) != 1) {
388 LOG(ERROR) << "EVP_DecryptInit_ex: failed";
389 return {};
390 }
391
392 if (EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, kAesGcmIvSize, NULL) != 1) {
393 LOG(ERROR) << "EVP_CIPHER_CTX_ctrl: failed setting nonce length";
394 return {};
395 }
396
397 if (EVP_DecryptInit_ex(ctx.get(), NULL, NULL, (unsigned char*)key.data(), nonce) != 1) {
398 LOG(ERROR) << "EVP_DecryptInit_ex: failed";
399 return {};
400 }
401
402 int numWritten;
403 if (additionalAuthenticatedData.size() > 0) {
404 if (EVP_DecryptUpdate(ctx.get(), NULL, &numWritten,
405 (unsigned char*)additionalAuthenticatedData.data(),
406 additionalAuthenticatedData.size()) != 1) {
407 LOG(ERROR) << "EVP_DecryptUpdate: failed for additionalAuthenticatedData";
408 return {};
409 }
410 if ((size_t)numWritten != additionalAuthenticatedData.size()) {
411 LOG(ERROR) << "EVP_DecryptUpdate: Unexpected outl=" << numWritten << " (expected "
412 << additionalAuthenticatedData.size() << ") for additionalAuthenticatedData";
413 return {};
414 }
415 }
416
417 if (EVP_DecryptUpdate(ctx.get(), (unsigned char*)plainText.data(), &numWritten, cipherText,
418 cipherTextSize) != 1) {
419 LOG(ERROR) << "EVP_DecryptUpdate: failed";
420 return {};
421 }
422 if (numWritten != cipherTextSize) {
423 LOG(ERROR) << "EVP_DecryptUpdate: Unexpected outl=" << numWritten << " (expected "
424 << cipherTextSize << ")";
425 return {};
426 }
427
428 if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kAesGcmTagSize, tag)) {
429 LOG(ERROR) << "EVP_CIPHER_CTX_ctrl: failed setting expected tag";
430 return {};
431 }
432
433 int ret = EVP_DecryptFinal_ex(ctx.get(), (unsigned char*)plainText.data() + numWritten,
434 &numWritten);
435 if (ret != 1) {
436 LOG(ERROR) << "EVP_DecryptFinal_ex: failed";
437 return {};
438 }
439 if (numWritten != 0) {
440 LOG(ERROR) << "EVP_DecryptFinal_ex: Unexpected non-zero outl=" << numWritten;
441 return {};
442 }
443
444 return plainText;
445 }
446
encryptAes128Gcm(const vector<uint8_t> & key,const vector<uint8_t> & nonce,const vector<uint8_t> & data,const vector<uint8_t> & additionalAuthenticatedData)447 optional<vector<uint8_t>> encryptAes128Gcm(const vector<uint8_t>& key, const vector<uint8_t>& nonce,
448 const vector<uint8_t>& data,
449 const vector<uint8_t>& additionalAuthenticatedData) {
450 if (key.size() != kAes128GcmKeySize) {
451 LOG(ERROR) << "key is not kAes128GcmKeySize bytes";
452 return {};
453 }
454 if (nonce.size() != kAesGcmIvSize) {
455 LOG(ERROR) << "nonce is not kAesGcmIvSize bytes";
456 return {};
457 }
458
459 // The result is the nonce (kAesGcmIvSize bytes), the ciphertext, and
460 // finally the tag (kAesGcmTagSize bytes).
461 vector<uint8_t> encryptedData;
462 encryptedData.resize(data.size() + kAesGcmIvSize + kAesGcmTagSize);
463 unsigned char* noncePtr = (unsigned char*)encryptedData.data();
464 unsigned char* cipherText = noncePtr + kAesGcmIvSize;
465 unsigned char* tag = cipherText + data.size();
466 memcpy(noncePtr, nonce.data(), kAesGcmIvSize);
467
468 auto ctx = EvpCipherCtxPtr(EVP_CIPHER_CTX_new());
469 if (ctx.get() == nullptr) {
470 LOG(ERROR) << "EVP_CIPHER_CTX_new: failed";
471 return {};
472 }
473
474 if (EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_gcm(), NULL, NULL, NULL) != 1) {
475 LOG(ERROR) << "EVP_EncryptInit_ex: failed";
476 return {};
477 }
478
479 if (EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, kAesGcmIvSize, NULL) != 1) {
480 LOG(ERROR) << "EVP_CIPHER_CTX_ctrl: failed setting nonce length";
481 return {};
482 }
483
484 if (EVP_EncryptInit_ex(ctx.get(), NULL, NULL, (unsigned char*)key.data(),
485 (unsigned char*)nonce.data()) != 1) {
486 LOG(ERROR) << "EVP_EncryptInit_ex: failed";
487 return {};
488 }
489
490 int numWritten;
491 if (additionalAuthenticatedData.size() > 0) {
492 if (EVP_EncryptUpdate(ctx.get(), NULL, &numWritten,
493 (unsigned char*)additionalAuthenticatedData.data(),
494 additionalAuthenticatedData.size()) != 1) {
495 LOG(ERROR) << "EVP_EncryptUpdate: failed for additionalAuthenticatedData";
496 return {};
497 }
498 if ((size_t)numWritten != additionalAuthenticatedData.size()) {
499 LOG(ERROR) << "EVP_EncryptUpdate: Unexpected outl=" << numWritten << " (expected "
500 << additionalAuthenticatedData.size() << ") for additionalAuthenticatedData";
501 return {};
502 }
503 }
504
505 if (data.size() > 0) {
506 if (EVP_EncryptUpdate(ctx.get(), cipherText, &numWritten, (unsigned char*)data.data(),
507 data.size()) != 1) {
508 LOG(ERROR) << "EVP_EncryptUpdate: failed";
509 return {};
510 }
511 if ((size_t)numWritten != data.size()) {
512 LOG(ERROR) << "EVP_EncryptUpdate: Unexpected outl=" << numWritten << " (expected "
513 << data.size() << ")";
514 return {};
515 }
516 }
517
518 if (EVP_EncryptFinal_ex(ctx.get(), cipherText + numWritten, &numWritten) != 1) {
519 LOG(ERROR) << "EVP_EncryptFinal_ex: failed";
520 return {};
521 }
522 if (numWritten != 0) {
523 LOG(ERROR) << "EVP_EncryptFinal_ex: Unexpected non-zero outl=" << numWritten;
524 return {};
525 }
526
527 if (EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kAesGcmTagSize, tag) != 1) {
528 LOG(ERROR) << "EVP_CIPHER_CTX_ctrl: failed getting tag";
529 return {};
530 }
531
532 return encryptedData;
533 }
534
535 struct EC_KEY_Deleter {
operator ()android::hardware::identity::support::EC_KEY_Deleter536 void operator()(EC_KEY* key) const {
537 if (key != nullptr) {
538 EC_KEY_free(key);
539 }
540 }
541 };
542 using EC_KEY_Ptr = unique_ptr<EC_KEY, EC_KEY_Deleter>;
543
544 struct EVP_PKEY_Deleter {
operator ()android::hardware::identity::support::EVP_PKEY_Deleter545 void operator()(EVP_PKEY* key) const {
546 if (key != nullptr) {
547 EVP_PKEY_free(key);
548 }
549 }
550 };
551 using EVP_PKEY_Ptr = unique_ptr<EVP_PKEY, EVP_PKEY_Deleter>;
552
553 struct EVP_PKEY_CTX_Deleter {
operator ()android::hardware::identity::support::EVP_PKEY_CTX_Deleter554 void operator()(EVP_PKEY_CTX* ctx) const {
555 if (ctx != nullptr) {
556 EVP_PKEY_CTX_free(ctx);
557 }
558 }
559 };
560 using EVP_PKEY_CTX_Ptr = unique_ptr<EVP_PKEY_CTX, EVP_PKEY_CTX_Deleter>;
561
562 struct EC_GROUP_Deleter {
operator ()android::hardware::identity::support::EC_GROUP_Deleter563 void operator()(EC_GROUP* group) const {
564 if (group != nullptr) {
565 EC_GROUP_free(group);
566 }
567 }
568 };
569 using EC_GROUP_Ptr = unique_ptr<EC_GROUP, EC_GROUP_Deleter>;
570
571 struct EC_POINT_Deleter {
operator ()android::hardware::identity::support::EC_POINT_Deleter572 void operator()(EC_POINT* point) const {
573 if (point != nullptr) {
574 EC_POINT_free(point);
575 }
576 }
577 };
578
579 using EC_POINT_Ptr = unique_ptr<EC_POINT, EC_POINT_Deleter>;
580
581 struct ECDSA_SIG_Deleter {
operator ()android::hardware::identity::support::ECDSA_SIG_Deleter582 void operator()(ECDSA_SIG* sig) const {
583 if (sig != nullptr) {
584 ECDSA_SIG_free(sig);
585 }
586 }
587 };
588 using ECDSA_SIG_Ptr = unique_ptr<ECDSA_SIG, ECDSA_SIG_Deleter>;
589
590 struct X509_Deleter {
operator ()android::hardware::identity::support::X509_Deleter591 void operator()(X509* x509) const {
592 if (x509 != nullptr) {
593 X509_free(x509);
594 }
595 }
596 };
597 using X509_Ptr = unique_ptr<X509, X509_Deleter>;
598
599 struct PKCS12_Deleter {
operator ()android::hardware::identity::support::PKCS12_Deleter600 void operator()(PKCS12* pkcs12) const {
601 if (pkcs12 != nullptr) {
602 PKCS12_free(pkcs12);
603 }
604 }
605 };
606 using PKCS12_Ptr = unique_ptr<PKCS12, PKCS12_Deleter>;
607
608 struct BIGNUM_Deleter {
operator ()android::hardware::identity::support::BIGNUM_Deleter609 void operator()(BIGNUM* bignum) const {
610 if (bignum != nullptr) {
611 BN_free(bignum);
612 }
613 }
614 };
615 using BIGNUM_Ptr = unique_ptr<BIGNUM, BIGNUM_Deleter>;
616
617 struct ASN1_INTEGER_Deleter {
operator ()android::hardware::identity::support::ASN1_INTEGER_Deleter618 void operator()(ASN1_INTEGER* value) const {
619 if (value != nullptr) {
620 ASN1_INTEGER_free(value);
621 }
622 }
623 };
624 using ASN1_INTEGER_Ptr = unique_ptr<ASN1_INTEGER, ASN1_INTEGER_Deleter>;
625
626 struct ASN1_TIME_Deleter {
operator ()android::hardware::identity::support::ASN1_TIME_Deleter627 void operator()(ASN1_TIME* value) const {
628 if (value != nullptr) {
629 ASN1_TIME_free(value);
630 }
631 }
632 };
633 using ASN1_TIME_Ptr = unique_ptr<ASN1_TIME, ASN1_TIME_Deleter>;
634
635 struct X509_NAME_Deleter {
operator ()android::hardware::identity::support::X509_NAME_Deleter636 void operator()(X509_NAME* value) const {
637 if (value != nullptr) {
638 X509_NAME_free(value);
639 }
640 }
641 };
642 using X509_NAME_Ptr = unique_ptr<X509_NAME, X509_NAME_Deleter>;
643
certificateChainJoin(const vector<vector<uint8_t>> & certificateChain)644 vector<uint8_t> certificateChainJoin(const vector<vector<uint8_t>>& certificateChain) {
645 vector<uint8_t> ret;
646 for (const vector<uint8_t>& certificate : certificateChain) {
647 ret.insert(ret.end(), certificate.begin(), certificate.end());
648 }
649 return ret;
650 }
651
certificateChainSplit(const vector<uint8_t> & certificateChain)652 optional<vector<vector<uint8_t>>> certificateChainSplit(const vector<uint8_t>& certificateChain) {
653 const unsigned char* pStart = (unsigned char*)certificateChain.data();
654 const unsigned char* p = pStart;
655 const unsigned char* pEnd = p + certificateChain.size();
656 vector<vector<uint8_t>> certificates;
657 while (p < pEnd) {
658 size_t begin = p - pStart;
659 auto x509 = X509_Ptr(d2i_X509(nullptr, &p, pEnd - p));
660 size_t next = p - pStart;
661 if (x509 == nullptr) {
662 LOG(ERROR) << "Error parsing X509 certificate";
663 return {};
664 }
665 vector<uint8_t> cert =
666 vector<uint8_t>(certificateChain.begin() + begin, certificateChain.begin() + next);
667 certificates.push_back(std::move(cert));
668 }
669 return certificates;
670 }
671
parseX509Certificates(const vector<uint8_t> & certificateChain,vector<X509_Ptr> & parsedCertificates)672 static bool parseX509Certificates(const vector<uint8_t>& certificateChain,
673 vector<X509_Ptr>& parsedCertificates) {
674 const unsigned char* p = (unsigned char*)certificateChain.data();
675 const unsigned char* pEnd = p + certificateChain.size();
676 parsedCertificates.resize(0);
677 while (p < pEnd) {
678 auto x509 = X509_Ptr(d2i_X509(nullptr, &p, pEnd - p));
679 if (x509 == nullptr) {
680 LOG(ERROR) << "Error parsing X509 certificate";
681 return false;
682 }
683 parsedCertificates.push_back(std::move(x509));
684 }
685 return true;
686 }
687
certificateSignedByPublicKey(const vector<uint8_t> & certificate,const vector<uint8_t> & publicKey)688 bool certificateSignedByPublicKey(const vector<uint8_t>& certificate,
689 const vector<uint8_t>& publicKey) {
690 const unsigned char* p = certificate.data();
691 auto x509 = X509_Ptr(d2i_X509(nullptr, &p, certificate.size()));
692 if (x509 == nullptr) {
693 LOG(ERROR) << "Error parsing X509 certificate";
694 return false;
695 }
696
697 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
698 auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
699 if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
700 1) {
701 LOG(ERROR) << "Error decoding publicKey";
702 return false;
703 }
704 auto ecKey = EC_KEY_Ptr(EC_KEY_new());
705 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
706 if (ecKey.get() == nullptr || pkey.get() == nullptr) {
707 LOG(ERROR) << "Memory allocation failed";
708 return false;
709 }
710 if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
711 LOG(ERROR) << "Error setting group";
712 return false;
713 }
714 if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
715 LOG(ERROR) << "Error setting point";
716 return false;
717 }
718 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
719 LOG(ERROR) << "Error setting key";
720 return false;
721 }
722
723 if (X509_verify(x509.get(), pkey.get()) != 1) {
724 return false;
725 }
726
727 return true;
728 }
729
730 // TODO: Right now the only check we perform is to check that each certificate
731 // is signed by its successor. We should - but currently don't - also check
732 // things like valid dates etc.
733 //
734 // It would be nice to use X509_verify_cert() instead of doing our own thing.
735 //
certificateChainValidate(const vector<uint8_t> & certificateChain)736 bool certificateChainValidate(const vector<uint8_t>& certificateChain) {
737 vector<X509_Ptr> certs;
738
739 if (!parseX509Certificates(certificateChain, certs)) {
740 LOG(ERROR) << "Error parsing X509 certificates";
741 return false;
742 }
743
744 if (certs.size() == 1) {
745 return true;
746 }
747
748 for (size_t n = 1; n < certs.size(); n++) {
749 const X509_Ptr& keyCert = certs[n - 1];
750 const X509_Ptr& signingCert = certs[n];
751 EVP_PKEY_Ptr signingPubkey(X509_get_pubkey(signingCert.get()));
752 if (X509_verify(keyCert.get(), signingPubkey.get()) != 1) {
753 LOG(ERROR) << "Error validating cert at index " << n - 1
754 << " is signed by its successor";
755 return false;
756 }
757 }
758
759 return true;
760 }
761
checkEcDsaSignature(const vector<uint8_t> & digest,const vector<uint8_t> & signature,const vector<uint8_t> & publicKey)762 bool checkEcDsaSignature(const vector<uint8_t>& digest, const vector<uint8_t>& signature,
763 const vector<uint8_t>& publicKey) {
764 const unsigned char* p = (unsigned char*)signature.data();
765 auto sig = ECDSA_SIG_Ptr(d2i_ECDSA_SIG(nullptr, &p, signature.size()));
766 if (sig.get() == nullptr) {
767 LOG(ERROR) << "Error decoding DER encoded signature";
768 return false;
769 }
770
771 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
772 auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
773 if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
774 1) {
775 LOG(ERROR) << "Error decoding publicKey";
776 return false;
777 }
778 auto ecKey = EC_KEY_Ptr(EC_KEY_new());
779 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
780 if (ecKey.get() == nullptr || pkey.get() == nullptr) {
781 LOG(ERROR) << "Memory allocation failed";
782 return false;
783 }
784 if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
785 LOG(ERROR) << "Error setting group";
786 return false;
787 }
788 if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
789 LOG(ERROR) << "Error setting point";
790 return false;
791 }
792 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
793 LOG(ERROR) << "Error setting key";
794 return false;
795 }
796
797 int rc = ECDSA_do_verify(digest.data(), digest.size(), sig.get(), ecKey.get());
798 if (rc != 1) {
799 LOG(ERROR) << "Error verifying signature (rc=" << rc << ")";
800 return false;
801 }
802
803 return true;
804 }
805
sha256(const vector<uint8_t> & data)806 vector<uint8_t> sha256(const vector<uint8_t>& data) {
807 vector<uint8_t> ret;
808 ret.resize(SHA256_DIGEST_LENGTH);
809 SHA256_CTX ctx;
810 SHA256_Init(&ctx);
811 SHA256_Update(&ctx, data.data(), data.size());
812 SHA256_Final((unsigned char*)ret.data(), &ctx);
813 return ret;
814 }
815
signEcDsaDigest(const vector<uint8_t> & key,const vector<uint8_t> & dataDigest)816 optional<vector<uint8_t>> signEcDsaDigest(const vector<uint8_t>& key,
817 const vector<uint8_t>& dataDigest) {
818 auto bn = BIGNUM_Ptr(BN_bin2bn(key.data(), key.size(), nullptr));
819 if (bn.get() == nullptr) {
820 LOG(ERROR) << "Error creating BIGNUM";
821 return {};
822 }
823
824 auto ec_key = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
825 if (EC_KEY_set_private_key(ec_key.get(), bn.get()) != 1) {
826 LOG(ERROR) << "Error setting private key from BIGNUM";
827 return {};
828 }
829
830 ECDSA_SIG* sig = ECDSA_do_sign(dataDigest.data(), dataDigest.size(), ec_key.get());
831 if (sig == nullptr) {
832 LOG(ERROR) << "Error signing digest";
833 return {};
834 }
835 size_t len = i2d_ECDSA_SIG(sig, nullptr);
836 vector<uint8_t> signature;
837 signature.resize(len);
838 unsigned char* p = (unsigned char*)signature.data();
839 i2d_ECDSA_SIG(sig, &p);
840 ECDSA_SIG_free(sig);
841 return signature;
842 }
843
signEcDsa(const vector<uint8_t> & key,const vector<uint8_t> & data)844 optional<vector<uint8_t>> signEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data) {
845 return signEcDsaDigest(key, sha256(data));
846 }
847
hmacSha256(const vector<uint8_t> & key,const vector<uint8_t> & data)848 optional<vector<uint8_t>> hmacSha256(const vector<uint8_t>& key, const vector<uint8_t>& data) {
849 HMAC_CTX ctx;
850 HMAC_CTX_init(&ctx);
851 if (HMAC_Init_ex(&ctx, key.data(), key.size(), EVP_sha256(), nullptr /* impl */) != 1) {
852 LOG(ERROR) << "Error initializing HMAC_CTX";
853 return {};
854 }
855 if (HMAC_Update(&ctx, data.data(), data.size()) != 1) {
856 LOG(ERROR) << "Error updating HMAC_CTX";
857 return {};
858 }
859 vector<uint8_t> hmac;
860 hmac.resize(32);
861 unsigned int size = 0;
862 if (HMAC_Final(&ctx, hmac.data(), &size) != 1) {
863 LOG(ERROR) << "Error finalizing HMAC_CTX";
864 return {};
865 }
866 if (size != 32) {
867 LOG(ERROR) << "Expected 32 bytes from HMAC_Final, got " << size;
868 return {};
869 }
870 return hmac;
871 }
872
873 // Generates the attestation certificate with the parameters passed in. Note
874 // that the passed in |activeTimeMilliSeconds| |expireTimeMilliSeconds| are in
875 // milli seconds since epoch. We are setting them to milliseconds due to
876 // requirement in AuthorizationSet KM_DATE fields. The certificate created is
877 // actually in seconds.
createAttestation(const EVP_PKEY * key,const vector<uint8_t> & applicationId,const vector<uint8_t> & challenge,uint64_t activeTimeMilliSeconds,uint64_t expireTimeMilliSeconds)878 optional<vector<vector<uint8_t>>> createAttestation(const EVP_PKEY* key,
879 const vector<uint8_t>& applicationId,
880 const vector<uint8_t>& challenge,
881 uint64_t activeTimeMilliSeconds,
882 uint64_t expireTimeMilliSeconds) {
883 ::keymaster::AuthorizationSet auth_set(
884 ::keymaster::AuthorizationSetBuilder()
885 .Authorization(::keymaster::TAG_ATTESTATION_CHALLENGE, challenge.data(),
886 challenge.size())
887 .Authorization(::keymaster::TAG_ACTIVE_DATETIME, activeTimeMilliSeconds)
888 // Even though identity attestation hal said the application
889 // id should be in software enforced authentication set,
890 // keymaster portable lib expect the input in this
891 // parameter because the software enforced in input to keymaster
892 // refers to the key software enforced properties. And this
893 // parameter refers to properties of the attestation which
894 // includes app id.
895 .Authorization(::keymaster::TAG_ATTESTATION_APPLICATION_ID,
896 applicationId.data(), applicationId.size())
897 .Authorization(::keymaster::TAG_USAGE_EXPIRE_DATETIME, expireTimeMilliSeconds));
898
899 // Unique id and device id is not applicable for identity credential attestation,
900 // so we don't need to set those or application id.
901 ::keymaster::AuthorizationSet swEnforced(::keymaster::AuthorizationSetBuilder().Authorization(
902 ::keymaster::TAG_CREATION_DATETIME, activeTimeMilliSeconds));
903
904 ::keymaster::AuthorizationSet hwEnforced(
905 ::keymaster::AuthorizationSetBuilder()
906 .Authorization(::keymaster::TAG_PURPOSE, KM_PURPOSE_SIGN)
907 .Authorization(::keymaster::TAG_KEY_SIZE, 256)
908 .Authorization(::keymaster::TAG_ALGORITHM, KM_ALGORITHM_EC)
909 .Authorization(::keymaster::TAG_NO_AUTH_REQUIRED)
910 .Authorization(::keymaster::TAG_DIGEST, KM_DIGEST_SHA_2_256)
911 .Authorization(::keymaster::TAG_EC_CURVE, KM_EC_CURVE_P_256)
912 .Authorization(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY));
913
914 const keymaster_cert_chain_t* attestation_chain =
915 ::keymaster::getAttestationChain(KM_ALGORITHM_EC, nullptr);
916
917 if (attestation_chain == nullptr) {
918 LOG(ERROR) << "Error getting attestation chain";
919 return {};
920 }
921
922 const keymaster_key_blob_t* attestation_signing_key =
923 ::keymaster::getAttestationKey(KM_ALGORITHM_EC, nullptr);
924 if (attestation_signing_key == nullptr) {
925 LOG(ERROR) << "Error getting attestation key";
926 return {};
927 }
928
929 keymaster_error_t error;
930 ::keymaster::CertChainPtr cert_chain_out;
931 ::keymaster::PureSoftKeymasterContext context;
932
933 // set identity version to 10 per hal requirements specified in IWriteableCredential.hal
934 // For now, the identity version in the attestation is set in the keymaster
935 // version field in the portable keymaster lib, which is a bit misleading.
936 uint identity_version = 10;
937 error = generate_attestation_from_EVP(key, swEnforced, hwEnforced, auth_set, context,
938 identity_version, *attestation_chain,
939 *attestation_signing_key, &cert_chain_out);
940
941 if (KM_ERROR_OK != error || !cert_chain_out) {
942 LOG(ERROR) << "Error generate attestation from EVP key" << error;
943 return {};
944 }
945
946 // translate certificate format from keymaster_cert_chain_t to vector<uint8_t>.
947 vector<vector<uint8_t>> attestationCertificate;
948 for (int i = 0; i < cert_chain_out->entry_count; i++) {
949 attestationCertificate.insert(
950 attestationCertificate.end(),
951 vector<uint8_t>(
952 cert_chain_out->entries[i].data,
953 cert_chain_out->entries[i].data + cert_chain_out->entries[i].data_length));
954 }
955
956 return attestationCertificate;
957 }
958
createEcKeyPairAndAttestation(const vector<uint8_t> & challenge,const vector<uint8_t> & applicationId)959 optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
960 const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId) {
961 auto ec_key = ::keymaster::EC_KEY_Ptr(EC_KEY_new());
962 auto pkey = ::keymaster::EVP_PKEY_Ptr(EVP_PKEY_new());
963 auto group = ::keymaster::EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
964
965 if (ec_key.get() == nullptr || pkey.get() == nullptr) {
966 LOG(ERROR) << "Memory allocation failed";
967 return {};
968 }
969
970 if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
971 EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
972 LOG(ERROR) << "Error generating key";
973 return {};
974 }
975
976 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()) != 1) {
977 LOG(ERROR) << "Error getting private key";
978 return {};
979 }
980
981 uint64_t now = time(nullptr);
982 uint64_t secondsInOneYear = 365 * 24 * 60 * 60;
983 uint64_t expireTimeMs = (now + secondsInOneYear) * 1000;
984
985 optional<vector<vector<uint8_t>>> attestationCert =
986 createAttestation(pkey.get(), applicationId, challenge, now * 1000, expireTimeMs);
987 if (!attestationCert) {
988 LOG(ERROR) << "Error create attestation from key and challenge";
989 return {};
990 }
991
992 int size = i2d_PrivateKey(pkey.get(), nullptr);
993 if (size == 0) {
994 LOG(ERROR) << "Error generating public key encoding";
995 return {};
996 }
997
998 vector<uint8_t> keyPair(size);
999 unsigned char* p = keyPair.data();
1000 i2d_PrivateKey(pkey.get(), &p);
1001
1002 return make_pair(keyPair, attestationCert.value());
1003 }
1004
createAttestationForEcPublicKey(const vector<uint8_t> & publicKey,const vector<uint8_t> & challenge,const vector<uint8_t> & applicationId)1005 optional<vector<vector<uint8_t>>> createAttestationForEcPublicKey(
1006 const vector<uint8_t>& publicKey, const vector<uint8_t>& challenge,
1007 const vector<uint8_t>& applicationId) {
1008 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
1009 auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
1010 if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
1011 1) {
1012 LOG(ERROR) << "Error decoding publicKey";
1013 return {};
1014 }
1015 auto ecKey = EC_KEY_Ptr(EC_KEY_new());
1016 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1017 if (ecKey.get() == nullptr || pkey.get() == nullptr) {
1018 LOG(ERROR) << "Memory allocation failed";
1019 return {};
1020 }
1021 if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
1022 LOG(ERROR) << "Error setting group";
1023 return {};
1024 }
1025 if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
1026 LOG(ERROR) << "Error setting point";
1027 return {};
1028 }
1029 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1030 LOG(ERROR) << "Error setting key";
1031 return {};
1032 }
1033
1034 uint64_t now = (std::chrono::duration_cast<std::chrono::nanoseconds>(
1035 std::chrono::system_clock::now().time_since_epoch()).
1036 count()/ 1000000000);
1037 uint64_t secondsInOneYear = 365 * 24 * 60 * 60;
1038 uint64_t expireTimeMs = (now + secondsInOneYear) * 1000;
1039
1040 optional<vector<vector<uint8_t>>> attestationCert =
1041 createAttestation(pkey.get(), applicationId, challenge, now * 1000, expireTimeMs);
1042 if (!attestationCert) {
1043 LOG(ERROR) << "Error create attestation from key and challenge";
1044 return {};
1045 }
1046
1047 return attestationCert.value();
1048 }
1049
createEcKeyPair()1050 optional<vector<uint8_t>> createEcKeyPair() {
1051 auto ec_key = EC_KEY_Ptr(EC_KEY_new());
1052 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1053 if (ec_key.get() == nullptr || pkey.get() == nullptr) {
1054 LOG(ERROR) << "Memory allocation failed";
1055 return {};
1056 }
1057
1058 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
1059 if (group.get() == nullptr) {
1060 LOG(ERROR) << "Error creating EC group by curve name";
1061 return {};
1062 }
1063
1064 if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
1065 EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
1066 LOG(ERROR) << "Error generating key";
1067 return {};
1068 }
1069
1070 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()) != 1) {
1071 LOG(ERROR) << "Error getting private key";
1072 return {};
1073 }
1074
1075 int size = i2d_PrivateKey(pkey.get(), nullptr);
1076 if (size == 0) {
1077 LOG(ERROR) << "Error generating public key encoding";
1078 return {};
1079 }
1080 vector<uint8_t> keyPair;
1081 keyPair.resize(size);
1082 unsigned char* p = keyPair.data();
1083 i2d_PrivateKey(pkey.get(), &p);
1084 return keyPair;
1085 }
1086
ecKeyPairGetPublicKey(const vector<uint8_t> & keyPair)1087 optional<vector<uint8_t>> ecKeyPairGetPublicKey(const vector<uint8_t>& keyPair) {
1088 const unsigned char* p = (const unsigned char*)keyPair.data();
1089 auto pkey = EVP_PKEY_Ptr(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, keyPair.size()));
1090 if (pkey.get() == nullptr) {
1091 LOG(ERROR) << "Error parsing keyPair";
1092 return {};
1093 }
1094
1095 auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
1096 if (ecKey.get() == nullptr) {
1097 LOG(ERROR) << "Failed getting EC key";
1098 return {};
1099 }
1100
1101 auto ecGroup = EC_KEY_get0_group(ecKey.get());
1102 auto ecPoint = EC_KEY_get0_public_key(ecKey.get());
1103 int size = EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0,
1104 nullptr);
1105 if (size == 0) {
1106 LOG(ERROR) << "Error generating public key encoding";
1107 return {};
1108 }
1109
1110 vector<uint8_t> publicKey;
1111 publicKey.resize(size);
1112 EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
1113 publicKey.size(), nullptr);
1114 return publicKey;
1115 }
1116
ecKeyPairGetPrivateKey(const vector<uint8_t> & keyPair)1117 optional<vector<uint8_t>> ecKeyPairGetPrivateKey(const vector<uint8_t>& keyPair) {
1118 const unsigned char* p = (const unsigned char*)keyPair.data();
1119 auto pkey = EVP_PKEY_Ptr(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, keyPair.size()));
1120 if (pkey.get() == nullptr) {
1121 LOG(ERROR) << "Error parsing keyPair";
1122 return {};
1123 }
1124
1125 auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
1126 if (ecKey.get() == nullptr) {
1127 LOG(ERROR) << "Failed getting EC key";
1128 return {};
1129 }
1130
1131 const BIGNUM* bignum = EC_KEY_get0_private_key(ecKey.get());
1132 if (bignum == nullptr) {
1133 LOG(ERROR) << "Error getting bignum from private key";
1134 return {};
1135 }
1136 vector<uint8_t> privateKey;
1137 privateKey.resize(BN_num_bytes(bignum));
1138 BN_bn2bin(bignum, privateKey.data());
1139 return privateKey;
1140 }
1141
ecPrivateKeyToKeyPair(const vector<uint8_t> & privateKey)1142 optional<vector<uint8_t>> ecPrivateKeyToKeyPair(const vector<uint8_t>& privateKey) {
1143 auto bn = BIGNUM_Ptr(BN_bin2bn(privateKey.data(), privateKey.size(), nullptr));
1144 if (bn.get() == nullptr) {
1145 LOG(ERROR) << "Error creating BIGNUM";
1146 return {};
1147 }
1148
1149 auto ecKey = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
1150 if (EC_KEY_set_private_key(ecKey.get(), bn.get()) != 1) {
1151 LOG(ERROR) << "Error setting private key from BIGNUM";
1152 return {};
1153 }
1154
1155 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1156 if (pkey.get() == nullptr) {
1157 LOG(ERROR) << "Memory allocation failed";
1158 return {};
1159 }
1160
1161 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1162 LOG(ERROR) << "Error getting private key";
1163 return {};
1164 }
1165
1166 int size = i2d_PrivateKey(pkey.get(), nullptr);
1167 if (size == 0) {
1168 LOG(ERROR) << "Error generating public key encoding";
1169 return {};
1170 }
1171 vector<uint8_t> keyPair;
1172 keyPair.resize(size);
1173 unsigned char* p = keyPair.data();
1174 i2d_PrivateKey(pkey.get(), &p);
1175 return keyPair;
1176 }
1177
ecKeyPairGetPkcs12(const vector<uint8_t> & keyPair,const string & name,const string & serialDecimal,const string & issuer,const string & subject,time_t validityNotBefore,time_t validityNotAfter)1178 optional<vector<uint8_t>> ecKeyPairGetPkcs12(const vector<uint8_t>& keyPair, const string& name,
1179 const string& serialDecimal, const string& issuer,
1180 const string& subject, time_t validityNotBefore,
1181 time_t validityNotAfter) {
1182 const unsigned char* p = (const unsigned char*)keyPair.data();
1183 auto pkey = EVP_PKEY_Ptr(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, keyPair.size()));
1184 if (pkey.get() == nullptr) {
1185 LOG(ERROR) << "Error parsing keyPair";
1186 return {};
1187 }
1188
1189 auto x509 = X509_Ptr(X509_new());
1190 if (!x509.get()) {
1191 LOG(ERROR) << "Error creating X509 certificate";
1192 return {};
1193 }
1194
1195 if (!X509_set_version(x509.get(), 2 /* version 3, but zero-based */)) {
1196 LOG(ERROR) << "Error setting version to 3";
1197 return {};
1198 }
1199
1200 if (X509_set_pubkey(x509.get(), pkey.get()) != 1) {
1201 LOG(ERROR) << "Error setting public key";
1202 return {};
1203 }
1204
1205 BIGNUM* bignumSerial = nullptr;
1206 if (BN_dec2bn(&bignumSerial, serialDecimal.c_str()) == 0) {
1207 LOG(ERROR) << "Error parsing serial";
1208 return {};
1209 }
1210 auto bignumSerialPtr = BIGNUM_Ptr(bignumSerial);
1211 auto asnSerial = ASN1_INTEGER_Ptr(BN_to_ASN1_INTEGER(bignumSerial, nullptr));
1212 if (X509_set_serialNumber(x509.get(), asnSerial.get()) != 1) {
1213 LOG(ERROR) << "Error setting serial";
1214 return {};
1215 }
1216
1217 auto x509Issuer = X509_NAME_Ptr(X509_NAME_new());
1218 if (x509Issuer.get() == nullptr ||
1219 X509_NAME_add_entry_by_txt(x509Issuer.get(), "CN", MBSTRING_ASC,
1220 (const uint8_t*)issuer.c_str(), issuer.size(), -1 /* loc */,
1221 0 /* set */) != 1 ||
1222 X509_set_issuer_name(x509.get(), x509Issuer.get()) != 1) {
1223 LOG(ERROR) << "Error setting issuer";
1224 return {};
1225 }
1226
1227 auto x509Subject = X509_NAME_Ptr(X509_NAME_new());
1228 if (x509Subject.get() == nullptr ||
1229 X509_NAME_add_entry_by_txt(x509Subject.get(), "CN", MBSTRING_ASC,
1230 (const uint8_t*)subject.c_str(), subject.size(), -1 /* loc */,
1231 0 /* set */) != 1 ||
1232 X509_set_subject_name(x509.get(), x509Subject.get()) != 1) {
1233 LOG(ERROR) << "Error setting subject";
1234 return {};
1235 }
1236
1237 auto asnNotBefore = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotBefore));
1238 if (asnNotBefore.get() == nullptr || X509_set_notBefore(x509.get(), asnNotBefore.get()) != 1) {
1239 LOG(ERROR) << "Error setting notBefore";
1240 return {};
1241 }
1242
1243 auto asnNotAfter = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotAfter));
1244 if (asnNotAfter.get() == nullptr || X509_set_notAfter(x509.get(), asnNotAfter.get()) != 1) {
1245 LOG(ERROR) << "Error setting notAfter";
1246 return {};
1247 }
1248
1249 if (X509_sign(x509.get(), pkey.get(), EVP_sha256()) == 0) {
1250 LOG(ERROR) << "Error signing X509 certificate";
1251 return {};
1252 }
1253
1254 // Ideally we wouldn't encrypt it (we're only using this function for
1255 // sending a key-pair over binder to the Android app) but BoringSSL does not
1256 // support this: from pkcs8_x509.c in BoringSSL: "In OpenSSL, -1 here means
1257 // to use no encryption, which we do not currently support."
1258 //
1259 // Passing nullptr as |pass|, though, means "no password". So we'll do that.
1260 // Compare with the receiving side - CredstoreIdentityCredential.java - where
1261 // an empty char[] is passed as the password.
1262 //
1263 auto pkcs12 = PKCS12_Ptr(PKCS12_create(nullptr, name.c_str(), pkey.get(), x509.get(),
1264 nullptr, // ca
1265 0, // nid_key
1266 0, // nid_cert
1267 0, // iter,
1268 0, // mac_iter,
1269 0)); // keytype
1270 if (pkcs12.get() == nullptr) {
1271 char buf[128];
1272 long errCode = ERR_get_error();
1273 ERR_error_string_n(errCode, buf, sizeof buf);
1274 LOG(ERROR) << "Error creating PKCS12, code " << errCode << ": " << buf;
1275 return {};
1276 }
1277
1278 unsigned char* buffer = nullptr;
1279 int length = i2d_PKCS12(pkcs12.get(), &buffer);
1280 if (length < 0) {
1281 LOG(ERROR) << "Error encoding PKCS12";
1282 return {};
1283 }
1284 vector<uint8_t> pkcs12Bytes;
1285 pkcs12Bytes.resize(length);
1286 memcpy(pkcs12Bytes.data(), buffer, length);
1287 OPENSSL_free(buffer);
1288
1289 return pkcs12Bytes;
1290 }
1291
ecPublicKeyGenerateCertificate(const vector<uint8_t> & publicKey,const vector<uint8_t> & signingKey,const string & serialDecimal,const string & issuer,const string & subject,time_t validityNotBefore,time_t validityNotAfter)1292 optional<vector<uint8_t>> ecPublicKeyGenerateCertificate(
1293 const vector<uint8_t>& publicKey, const vector<uint8_t>& signingKey,
1294 const string& serialDecimal, const string& issuer, const string& subject,
1295 time_t validityNotBefore, time_t validityNotAfter) {
1296 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
1297 auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
1298 if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
1299 1) {
1300 LOG(ERROR) << "Error decoding publicKey";
1301 return {};
1302 }
1303 auto ecKey = EC_KEY_Ptr(EC_KEY_new());
1304 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1305 if (ecKey.get() == nullptr || pkey.get() == nullptr) {
1306 LOG(ERROR) << "Memory allocation failed";
1307 return {};
1308 }
1309 if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
1310 LOG(ERROR) << "Error setting group";
1311 return {};
1312 }
1313 if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
1314 LOG(ERROR) << "Error setting point";
1315 return {};
1316 }
1317 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1318 LOG(ERROR) << "Error setting key";
1319 return {};
1320 }
1321
1322 auto bn = BIGNUM_Ptr(BN_bin2bn(signingKey.data(), signingKey.size(), nullptr));
1323 if (bn.get() == nullptr) {
1324 LOG(ERROR) << "Error creating BIGNUM for private key";
1325 return {};
1326 }
1327 auto privEcKey = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
1328 if (EC_KEY_set_private_key(privEcKey.get(), bn.get()) != 1) {
1329 LOG(ERROR) << "Error setting private key from BIGNUM";
1330 return {};
1331 }
1332 auto privPkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1333 if (EVP_PKEY_set1_EC_KEY(privPkey.get(), privEcKey.get()) != 1) {
1334 LOG(ERROR) << "Error setting private key";
1335 return {};
1336 }
1337
1338 auto x509 = X509_Ptr(X509_new());
1339 if (!x509.get()) {
1340 LOG(ERROR) << "Error creating X509 certificate";
1341 return {};
1342 }
1343
1344 if (!X509_set_version(x509.get(), 2 /* version 3, but zero-based */)) {
1345 LOG(ERROR) << "Error setting version to 3";
1346 return {};
1347 }
1348
1349 if (X509_set_pubkey(x509.get(), pkey.get()) != 1) {
1350 LOG(ERROR) << "Error setting public key";
1351 return {};
1352 }
1353
1354 BIGNUM* bignumSerial = nullptr;
1355 if (BN_dec2bn(&bignumSerial, serialDecimal.c_str()) == 0) {
1356 LOG(ERROR) << "Error parsing serial";
1357 return {};
1358 }
1359 auto bignumSerialPtr = BIGNUM_Ptr(bignumSerial);
1360 auto asnSerial = ASN1_INTEGER_Ptr(BN_to_ASN1_INTEGER(bignumSerial, nullptr));
1361 if (X509_set_serialNumber(x509.get(), asnSerial.get()) != 1) {
1362 LOG(ERROR) << "Error setting serial";
1363 return {};
1364 }
1365
1366 auto x509Issuer = X509_NAME_Ptr(X509_NAME_new());
1367 if (x509Issuer.get() == nullptr ||
1368 X509_NAME_add_entry_by_txt(x509Issuer.get(), "CN", MBSTRING_ASC,
1369 (const uint8_t*)issuer.c_str(), issuer.size(), -1 /* loc */,
1370 0 /* set */) != 1 ||
1371 X509_set_issuer_name(x509.get(), x509Issuer.get()) != 1) {
1372 LOG(ERROR) << "Error setting issuer";
1373 return {};
1374 }
1375
1376 auto x509Subject = X509_NAME_Ptr(X509_NAME_new());
1377 if (x509Subject.get() == nullptr ||
1378 X509_NAME_add_entry_by_txt(x509Subject.get(), "CN", MBSTRING_ASC,
1379 (const uint8_t*)subject.c_str(), subject.size(), -1 /* loc */,
1380 0 /* set */) != 1 ||
1381 X509_set_subject_name(x509.get(), x509Subject.get()) != 1) {
1382 LOG(ERROR) << "Error setting subject";
1383 return {};
1384 }
1385
1386 auto asnNotBefore = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotBefore));
1387 if (asnNotBefore.get() == nullptr || X509_set_notBefore(x509.get(), asnNotBefore.get()) != 1) {
1388 LOG(ERROR) << "Error setting notBefore";
1389 return {};
1390 }
1391
1392 auto asnNotAfter = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotAfter));
1393 if (asnNotAfter.get() == nullptr || X509_set_notAfter(x509.get(), asnNotAfter.get()) != 1) {
1394 LOG(ERROR) << "Error setting notAfter";
1395 return {};
1396 }
1397
1398 if (X509_sign(x509.get(), privPkey.get(), EVP_sha256()) == 0) {
1399 LOG(ERROR) << "Error signing X509 certificate";
1400 return {};
1401 }
1402
1403 unsigned char* buffer = nullptr;
1404 int length = i2d_X509(x509.get(), &buffer);
1405 if (length < 0) {
1406 LOG(ERROR) << "Error DER encoding X509 certificate";
1407 return {};
1408 }
1409
1410 vector<uint8_t> certificate;
1411 certificate.resize(length);
1412 memcpy(certificate.data(), buffer, length);
1413 OPENSSL_free(buffer);
1414 return certificate;
1415 }
1416
ecdh(const vector<uint8_t> & publicKey,const vector<uint8_t> & privateKey)1417 optional<vector<uint8_t>> ecdh(const vector<uint8_t>& publicKey,
1418 const vector<uint8_t>& privateKey) {
1419 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
1420 auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
1421 if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
1422 1) {
1423 LOG(ERROR) << "Error decoding publicKey";
1424 return {};
1425 }
1426 auto ecKey = EC_KEY_Ptr(EC_KEY_new());
1427 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1428 if (ecKey.get() == nullptr || pkey.get() == nullptr) {
1429 LOG(ERROR) << "Memory allocation failed";
1430 return {};
1431 }
1432 if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
1433 LOG(ERROR) << "Error setting group";
1434 return {};
1435 }
1436 if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
1437 LOG(ERROR) << "Error setting point";
1438 return {};
1439 }
1440 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1441 LOG(ERROR) << "Error setting key";
1442 return {};
1443 }
1444
1445 auto bn = BIGNUM_Ptr(BN_bin2bn(privateKey.data(), privateKey.size(), nullptr));
1446 if (bn.get() == nullptr) {
1447 LOG(ERROR) << "Error creating BIGNUM for private key";
1448 return {};
1449 }
1450 auto privEcKey = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
1451 if (EC_KEY_set_private_key(privEcKey.get(), bn.get()) != 1) {
1452 LOG(ERROR) << "Error setting private key from BIGNUM";
1453 return {};
1454 }
1455 auto privPkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1456 if (EVP_PKEY_set1_EC_KEY(privPkey.get(), privEcKey.get()) != 1) {
1457 LOG(ERROR) << "Error setting private key";
1458 return {};
1459 }
1460
1461 auto ctx = EVP_PKEY_CTX_Ptr(EVP_PKEY_CTX_new(privPkey.get(), NULL));
1462 if (ctx.get() == nullptr) {
1463 LOG(ERROR) << "Error creating context";
1464 return {};
1465 }
1466
1467 if (EVP_PKEY_derive_init(ctx.get()) != 1) {
1468 LOG(ERROR) << "Error initializing context";
1469 return {};
1470 }
1471
1472 if (EVP_PKEY_derive_set_peer(ctx.get(), pkey.get()) != 1) {
1473 LOG(ERROR) << "Error setting peer";
1474 return {};
1475 }
1476
1477 /* Determine buffer length for shared secret */
1478 size_t secretLen = 0;
1479 if (EVP_PKEY_derive(ctx.get(), NULL, &secretLen) != 1) {
1480 LOG(ERROR) << "Error determing length of shared secret";
1481 return {};
1482 }
1483 vector<uint8_t> sharedSecret;
1484 sharedSecret.resize(secretLen);
1485
1486 if (EVP_PKEY_derive(ctx.get(), sharedSecret.data(), &secretLen) != 1) {
1487 LOG(ERROR) << "Error deriving shared secret";
1488 return {};
1489 }
1490 return sharedSecret;
1491 }
1492
hkdf(const vector<uint8_t> & sharedSecret,const vector<uint8_t> & salt,const vector<uint8_t> & info,size_t size)1493 optional<vector<uint8_t>> hkdf(const vector<uint8_t>& sharedSecret, const vector<uint8_t>& salt,
1494 const vector<uint8_t>& info, size_t size) {
1495 vector<uint8_t> derivedKey;
1496 derivedKey.resize(size);
1497 if (HKDF(derivedKey.data(), derivedKey.size(), EVP_sha256(), sharedSecret.data(),
1498 sharedSecret.size(), salt.data(), salt.size(), info.data(), info.size()) != 1) {
1499 LOG(ERROR) << "Error deriving key";
1500 return {};
1501 }
1502 return derivedKey;
1503 }
1504
removeLeadingZeroes(vector<uint8_t> & vec)1505 void removeLeadingZeroes(vector<uint8_t>& vec) {
1506 while (vec.size() >= 1 && vec[0] == 0x00) {
1507 vec.erase(vec.begin());
1508 }
1509 }
1510
ecPublicKeyGetXandY(const vector<uint8_t> & publicKey)1511 tuple<bool, vector<uint8_t>, vector<uint8_t>> ecPublicKeyGetXandY(
1512 const vector<uint8_t>& publicKey) {
1513 if (publicKey.size() != 65 || publicKey[0] != 0x04) {
1514 LOG(ERROR) << "publicKey is not in the expected format";
1515 return std::make_tuple(false, vector<uint8_t>(), vector<uint8_t>());
1516 }
1517 vector<uint8_t> x, y;
1518 x.resize(32);
1519 y.resize(32);
1520 memcpy(x.data(), publicKey.data() + 1, 32);
1521 memcpy(y.data(), publicKey.data() + 33, 32);
1522
1523 removeLeadingZeroes(x);
1524 removeLeadingZeroes(y);
1525
1526 return std::make_tuple(true, x, y);
1527 }
1528
certificateChainGetTopMostKey(const vector<uint8_t> & certificateChain)1529 optional<vector<uint8_t>> certificateChainGetTopMostKey(const vector<uint8_t>& certificateChain) {
1530 vector<X509_Ptr> certs;
1531 if (!parseX509Certificates(certificateChain, certs)) {
1532 return {};
1533 }
1534 if (certs.size() < 1) {
1535 LOG(ERROR) << "No certificates in chain";
1536 return {};
1537 }
1538
1539 int algoId = OBJ_obj2nid(certs[0]->cert_info->key->algor->algorithm);
1540 if (algoId != NID_X9_62_id_ecPublicKey) {
1541 LOG(ERROR) << "Expected NID_X9_62_id_ecPublicKey, got " << OBJ_nid2ln(algoId);
1542 return {};
1543 }
1544
1545 auto pkey = EVP_PKEY_Ptr(X509_get_pubkey(certs[0].get()));
1546 if (pkey.get() == nullptr) {
1547 LOG(ERROR) << "No public key";
1548 return {};
1549 }
1550
1551 auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
1552 if (ecKey.get() == nullptr) {
1553 LOG(ERROR) << "Failed getting EC key";
1554 return {};
1555 }
1556
1557 auto ecGroup = EC_KEY_get0_group(ecKey.get());
1558 auto ecPoint = EC_KEY_get0_public_key(ecKey.get());
1559 int size = EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0,
1560 nullptr);
1561 if (size == 0) {
1562 LOG(ERROR) << "Error generating public key encoding";
1563 return {};
1564 }
1565 vector<uint8_t> publicKey;
1566 publicKey.resize(size);
1567 EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
1568 publicKey.size(), nullptr);
1569 return publicKey;
1570 }
1571
certificateFindPublicKey(const vector<uint8_t> & x509Certificate)1572 optional<pair<size_t, size_t>> certificateFindPublicKey(const vector<uint8_t>& x509Certificate) {
1573 vector<X509_Ptr> certs;
1574 if (!parseX509Certificates(x509Certificate, certs)) {
1575 return {};
1576 }
1577 if (certs.size() < 1) {
1578 LOG(ERROR) << "No certificates in chain";
1579 return {};
1580 }
1581
1582 auto pkey = EVP_PKEY_Ptr(X509_get_pubkey(certs[0].get()));
1583 if (pkey.get() == nullptr) {
1584 LOG(ERROR) << "No public key";
1585 return {};
1586 }
1587
1588 auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
1589 if (ecKey.get() == nullptr) {
1590 LOG(ERROR) << "Failed getting EC key";
1591 return {};
1592 }
1593
1594 auto ecGroup = EC_KEY_get0_group(ecKey.get());
1595 auto ecPoint = EC_KEY_get0_public_key(ecKey.get());
1596 int size = EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0,
1597 nullptr);
1598 if (size == 0) {
1599 LOG(ERROR) << "Error generating public key encoding";
1600 return {};
1601 }
1602 vector<uint8_t> publicKey;
1603 publicKey.resize(size);
1604 EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
1605 publicKey.size(), nullptr);
1606
1607 size_t publicKeyOffset = 0;
1608 size_t publicKeySize = (size_t)size;
1609 void* location = memmem((const void*)x509Certificate.data(), x509Certificate.size(),
1610 (const void*)publicKey.data(), publicKey.size());
1611
1612 if (location == NULL) {
1613 LOG(ERROR) << "Error finding publicKey from x509Certificate";
1614 return {};
1615 }
1616 publicKeyOffset = (size_t)((const char*)location - (const char*)x509Certificate.data());
1617
1618 return std::make_pair(publicKeyOffset, publicKeySize);
1619 }
1620
certificateTbsCertificate(const vector<uint8_t> & x509Certificate)1621 optional<pair<size_t, size_t>> certificateTbsCertificate(const vector<uint8_t>& x509Certificate) {
1622 vector<X509_Ptr> certs;
1623 if (!parseX509Certificates(x509Certificate, certs)) {
1624 return {};
1625 }
1626 if (certs.size() < 1) {
1627 LOG(ERROR) << "No certificates in chain";
1628 return {};
1629 }
1630
1631 unsigned char* buf = NULL;
1632 int len = i2d_re_X509_tbs(certs[0].get(), &buf);
1633 if ((len < 0) || (buf == NULL)) {
1634 LOG(ERROR) << "fail to extract tbsCertificate in x509Certificate";
1635 return {};
1636 }
1637
1638 vector<uint8_t> tbsCertificate(len);
1639 memcpy(tbsCertificate.data(), buf, len);
1640
1641 size_t tbsCertificateOffset = 0;
1642 size_t tbsCertificateSize = (size_t)len;
1643 void* location = memmem((const void*)x509Certificate.data(), x509Certificate.size(),
1644 (const void*)tbsCertificate.data(), tbsCertificate.size());
1645
1646 if (location == NULL) {
1647 LOG(ERROR) << "Error finding tbsCertificate from x509Certificate";
1648 return {};
1649 }
1650 tbsCertificateOffset = (size_t)((const char*)location - (const char*)x509Certificate.data());
1651
1652 return std::make_pair(tbsCertificateOffset, tbsCertificateSize);
1653 }
1654
certificateFindSignature(const vector<uint8_t> & x509Certificate)1655 optional<pair<size_t, size_t>> certificateFindSignature(const vector<uint8_t>& x509Certificate) {
1656 vector<X509_Ptr> certs;
1657 if (!parseX509Certificates(x509Certificate, certs)) {
1658 return {};
1659 }
1660 if (certs.size() < 1) {
1661 LOG(ERROR) << "No certificates in chain";
1662 return {};
1663 }
1664
1665 ASN1_BIT_STRING* psig;
1666 X509_ALGOR* palg;
1667 X509_get0_signature((const ASN1_BIT_STRING**)&psig, (const X509_ALGOR**)&palg, certs[0].get());
1668
1669 vector<char> signature(psig->length);
1670 memcpy(signature.data(), psig->data, psig->length);
1671
1672 size_t signatureOffset = 0;
1673 size_t signatureSize = (size_t)psig->length;
1674 void* location = memmem((const void*)x509Certificate.data(), x509Certificate.size(),
1675 (const void*)signature.data(), signature.size());
1676
1677 if (location == NULL) {
1678 LOG(ERROR) << "Error finding signature from x509Certificate";
1679 return {};
1680 }
1681 signatureOffset = (size_t)((const char*)location - (const char*)x509Certificate.data());
1682
1683 return std::make_pair(signatureOffset, signatureSize);
1684 }
1685
1686 // ---------------------------------------------------------------------------
1687 // COSE Utility Functions
1688 // ---------------------------------------------------------------------------
1689
coseBuildToBeSigned(const vector<uint8_t> & encodedProtectedHeaders,const vector<uint8_t> & data,const vector<uint8_t> & detachedContent)1690 vector<uint8_t> coseBuildToBeSigned(const vector<uint8_t>& encodedProtectedHeaders,
1691 const vector<uint8_t>& data,
1692 const vector<uint8_t>& detachedContent) {
1693 cppbor::Array sigStructure;
1694 sigStructure.add("Signature1");
1695 sigStructure.add(encodedProtectedHeaders);
1696
1697 // We currently don't support Externally Supplied Data (RFC 8152 section 4.3)
1698 // so external_aad is the empty bstr
1699 vector<uint8_t> emptyExternalAad;
1700 sigStructure.add(emptyExternalAad);
1701
1702 // Next field is the payload, independently of how it's transported (RFC
1703 // 8152 section 4.4). Since our API specifies only one of |data| and
1704 // |detachedContent| can be non-empty, it's simply just the non-empty one.
1705 if (data.size() > 0) {
1706 sigStructure.add(data);
1707 } else {
1708 sigStructure.add(detachedContent);
1709 }
1710 return sigStructure.encode();
1711 }
1712
coseEncodeHeaders(const cppbor::Map & protectedHeaders)1713 vector<uint8_t> coseEncodeHeaders(const cppbor::Map& protectedHeaders) {
1714 if (protectedHeaders.size() == 0) {
1715 cppbor::Bstr emptyBstr(vector<uint8_t>({}));
1716 return emptyBstr.encode();
1717 }
1718 return protectedHeaders.encode();
1719 }
1720
1721 // From https://tools.ietf.org/html/rfc8152
1722 const int COSE_LABEL_ALG = 1;
1723 const int COSE_LABEL_X5CHAIN = 33; // temporary identifier
1724
1725 // From "COSE Algorithms" registry
1726 const int COSE_ALG_ECDSA_256 = -7;
1727 const int COSE_ALG_HMAC_256_256 = 5;
1728
ecdsaSignatureCoseToDer(const vector<uint8_t> & ecdsaCoseSignature,vector<uint8_t> & ecdsaDerSignature)1729 bool ecdsaSignatureCoseToDer(const vector<uint8_t>& ecdsaCoseSignature,
1730 vector<uint8_t>& ecdsaDerSignature) {
1731 if (ecdsaCoseSignature.size() != 64) {
1732 LOG(ERROR) << "COSE signature length is " << ecdsaCoseSignature.size() << ", expected 64";
1733 return false;
1734 }
1735
1736 auto rBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data(), 32, nullptr));
1737 if (rBn.get() == nullptr) {
1738 LOG(ERROR) << "Error creating BIGNUM for r";
1739 return false;
1740 }
1741
1742 auto sBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data() + 32, 32, nullptr));
1743 if (sBn.get() == nullptr) {
1744 LOG(ERROR) << "Error creating BIGNUM for s";
1745 return false;
1746 }
1747
1748 ECDSA_SIG sig;
1749 sig.r = rBn.get();
1750 sig.s = sBn.get();
1751
1752 size_t len = i2d_ECDSA_SIG(&sig, nullptr);
1753 ecdsaDerSignature.resize(len);
1754 unsigned char* p = (unsigned char*)ecdsaDerSignature.data();
1755 i2d_ECDSA_SIG(&sig, &p);
1756
1757 return true;
1758 }
1759
ecdsaSignatureDerToCose(const vector<uint8_t> & ecdsaDerSignature,vector<uint8_t> & ecdsaCoseSignature)1760 bool ecdsaSignatureDerToCose(const vector<uint8_t>& ecdsaDerSignature,
1761 vector<uint8_t>& ecdsaCoseSignature) {
1762 ECDSA_SIG* sig;
1763 const unsigned char* p = ecdsaDerSignature.data();
1764 sig = d2i_ECDSA_SIG(nullptr, &p, ecdsaDerSignature.size());
1765 if (sig == nullptr) {
1766 LOG(ERROR) << "Error decoding DER signature";
1767 return false;
1768 }
1769
1770 ecdsaCoseSignature.clear();
1771 ecdsaCoseSignature.resize(64);
1772 if (BN_bn2binpad(sig->r, ecdsaCoseSignature.data(), 32) != 32) {
1773 LOG(ERROR) << "Error encoding r";
1774 return false;
1775 }
1776 if (BN_bn2binpad(sig->s, ecdsaCoseSignature.data() + 32, 32) != 32) {
1777 LOG(ERROR) << "Error encoding s";
1778 return false;
1779 }
1780 return true;
1781 }
1782
coseSignEcDsaWithSignature(const vector<uint8_t> & signatureToBeSigned,const vector<uint8_t> & data,const vector<uint8_t> & certificateChain)1783 optional<vector<uint8_t>> coseSignEcDsaWithSignature(const vector<uint8_t>& signatureToBeSigned,
1784 const vector<uint8_t>& data,
1785 const vector<uint8_t>& certificateChain) {
1786 if (signatureToBeSigned.size() != 64) {
1787 LOG(ERROR) << "Invalid size for signatureToBeSigned, expected 64 got "
1788 << signatureToBeSigned.size();
1789 return {};
1790 }
1791
1792 cppbor::Map unprotectedHeaders;
1793 cppbor::Map protectedHeaders;
1794
1795 protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_ECDSA_256);
1796
1797 if (certificateChain.size() != 0) {
1798 optional<vector<vector<uint8_t>>> certs = support::certificateChainSplit(certificateChain);
1799 if (!certs) {
1800 LOG(ERROR) << "Error splitting certificate chain";
1801 return {};
1802 }
1803 if (certs.value().size() == 1) {
1804 unprotectedHeaders.add(COSE_LABEL_X5CHAIN, certs.value()[0]);
1805 } else {
1806 cppbor::Array certArray;
1807 for (const vector<uint8_t>& cert : certs.value()) {
1808 certArray.add(cert);
1809 }
1810 unprotectedHeaders.add(COSE_LABEL_X5CHAIN, std::move(certArray));
1811 }
1812 }
1813
1814 vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
1815
1816 cppbor::Array coseSign1;
1817 coseSign1.add(encodedProtectedHeaders);
1818 coseSign1.add(std::move(unprotectedHeaders));
1819 if (data.size() == 0) {
1820 cppbor::Null nullValue;
1821 coseSign1.add(std::move(nullValue));
1822 } else {
1823 coseSign1.add(data);
1824 }
1825 coseSign1.add(signatureToBeSigned);
1826 vector<uint8_t> signatureCoseSign1;
1827 signatureCoseSign1 = coseSign1.encode();
1828
1829 return signatureCoseSign1;
1830 }
1831
coseSignEcDsa(const vector<uint8_t> & key,const vector<uint8_t> & data,const vector<uint8_t> & detachedContent,const vector<uint8_t> & certificateChain)1832 optional<vector<uint8_t>> coseSignEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data,
1833 const vector<uint8_t>& detachedContent,
1834 const vector<uint8_t>& certificateChain) {
1835 cppbor::Map unprotectedHeaders;
1836 cppbor::Map protectedHeaders;
1837
1838 if (data.size() > 0 && detachedContent.size() > 0) {
1839 LOG(ERROR) << "data and detachedContent cannot both be non-empty";
1840 return {};
1841 }
1842
1843 protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_ECDSA_256);
1844
1845 if (certificateChain.size() != 0) {
1846 optional<vector<vector<uint8_t>>> certs = support::certificateChainSplit(certificateChain);
1847 if (!certs) {
1848 LOG(ERROR) << "Error splitting certificate chain";
1849 return {};
1850 }
1851 if (certs.value().size() == 1) {
1852 unprotectedHeaders.add(COSE_LABEL_X5CHAIN, certs.value()[0]);
1853 } else {
1854 cppbor::Array certArray;
1855 for (const vector<uint8_t>& cert : certs.value()) {
1856 certArray.add(cert);
1857 }
1858 unprotectedHeaders.add(COSE_LABEL_X5CHAIN, std::move(certArray));
1859 }
1860 }
1861
1862 vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
1863 vector<uint8_t> toBeSigned =
1864 coseBuildToBeSigned(encodedProtectedHeaders, data, detachedContent);
1865
1866 optional<vector<uint8_t>> derSignature = signEcDsa(key, toBeSigned);
1867 if (!derSignature) {
1868 LOG(ERROR) << "Error signing toBeSigned data";
1869 return {};
1870 }
1871 vector<uint8_t> coseSignature;
1872 if (!ecdsaSignatureDerToCose(derSignature.value(), coseSignature)) {
1873 LOG(ERROR) << "Error converting ECDSA signature from DER to COSE format";
1874 return {};
1875 }
1876
1877 cppbor::Array coseSign1;
1878 coseSign1.add(encodedProtectedHeaders);
1879 coseSign1.add(std::move(unprotectedHeaders));
1880 if (data.size() == 0) {
1881 cppbor::Null nullValue;
1882 coseSign1.add(std::move(nullValue));
1883 } else {
1884 coseSign1.add(data);
1885 }
1886 coseSign1.add(coseSignature);
1887 vector<uint8_t> signatureCoseSign1;
1888 signatureCoseSign1 = coseSign1.encode();
1889 return signatureCoseSign1;
1890 }
1891
coseCheckEcDsaSignature(const vector<uint8_t> & signatureCoseSign1,const vector<uint8_t> & detachedContent,const vector<uint8_t> & publicKey)1892 bool coseCheckEcDsaSignature(const vector<uint8_t>& signatureCoseSign1,
1893 const vector<uint8_t>& detachedContent,
1894 const vector<uint8_t>& publicKey) {
1895 auto [item, _, message] = cppbor::parse(signatureCoseSign1);
1896 if (item == nullptr) {
1897 LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
1898 return false;
1899 }
1900 const cppbor::Array* array = item->asArray();
1901 if (array == nullptr) {
1902 LOG(ERROR) << "Value for COSE_Sign1 is not an array";
1903 return false;
1904 }
1905 if (array->size() != 4) {
1906 LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
1907 return false;
1908 }
1909
1910 const cppbor::Bstr* encodedProtectedHeadersBstr = (*array)[0]->asBstr();
1911 ;
1912 if (encodedProtectedHeadersBstr == nullptr) {
1913 LOG(ERROR) << "Value for encodedProtectedHeaders is not a bstr";
1914 return false;
1915 }
1916 const vector<uint8_t> encodedProtectedHeaders = encodedProtectedHeadersBstr->value();
1917
1918 const cppbor::Map* unprotectedHeaders = (*array)[1]->asMap();
1919 if (unprotectedHeaders == nullptr) {
1920 LOG(ERROR) << "Value for unprotectedHeaders is not a map";
1921 return false;
1922 }
1923
1924 vector<uint8_t> data;
1925 const cppbor::Simple* payloadAsSimple = (*array)[2]->asSimple();
1926 if (payloadAsSimple != nullptr) {
1927 if (payloadAsSimple->asNull() == nullptr) {
1928 LOG(ERROR) << "Value for payload is not null or a bstr";
1929 return false;
1930 }
1931 } else {
1932 const cppbor::Bstr* payloadAsBstr = (*array)[2]->asBstr();
1933 if (payloadAsBstr == nullptr) {
1934 LOG(ERROR) << "Value for payload is not null or a bstr";
1935 return false;
1936 }
1937 data = payloadAsBstr->value(); // TODO: avoid copy
1938 }
1939
1940 if (data.size() > 0 && detachedContent.size() > 0) {
1941 LOG(ERROR) << "data and detachedContent cannot both be non-empty";
1942 return false;
1943 }
1944
1945 const cppbor::Bstr* signatureBstr = (*array)[3]->asBstr();
1946 if (signatureBstr == nullptr) {
1947 LOG(ERROR) << "Value for signature is a bstr";
1948 return false;
1949 }
1950 const vector<uint8_t>& coseSignature = signatureBstr->value();
1951
1952 vector<uint8_t> derSignature;
1953 if (!ecdsaSignatureCoseToDer(coseSignature, derSignature)) {
1954 LOG(ERROR) << "Error converting ECDSA signature from COSE to DER format";
1955 return false;
1956 }
1957
1958 vector<uint8_t> toBeSigned =
1959 coseBuildToBeSigned(encodedProtectedHeaders, data, detachedContent);
1960 if (!checkEcDsaSignature(support::sha256(toBeSigned), derSignature, publicKey)) {
1961 LOG(ERROR) << "Signature check failed";
1962 return false;
1963 }
1964 return true;
1965 }
1966
1967 // Extracts the signature (of the ToBeSigned CBOR) from a COSE_Sign1.
coseSignGetSignature(const vector<uint8_t> & signatureCoseSign1)1968 optional<vector<uint8_t>> coseSignGetSignature(const vector<uint8_t>& signatureCoseSign1) {
1969 auto [item, _, message] = cppbor::parse(signatureCoseSign1);
1970 if (item == nullptr) {
1971 LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
1972 return {};
1973 }
1974 const cppbor::Array* array = item->asArray();
1975 if (array == nullptr) {
1976 LOG(ERROR) << "Value for COSE_Sign1 is not an array";
1977 return {};
1978 }
1979 if (array->size() != 4) {
1980 LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
1981 return {};
1982 }
1983
1984 vector<uint8_t> signature;
1985 const cppbor::Bstr* signatureAsBstr = (*array)[3]->asBstr();
1986 if (signatureAsBstr == nullptr) {
1987 LOG(ERROR) << "Value for signature is not a bstr";
1988 return {};
1989 }
1990 // Copy payload into |data|
1991 signature = signatureAsBstr->value();
1992
1993 return signature;
1994 }
1995
coseSignGetPayload(const vector<uint8_t> & signatureCoseSign1)1996 optional<vector<uint8_t>> coseSignGetPayload(const vector<uint8_t>& signatureCoseSign1) {
1997 auto [item, _, message] = cppbor::parse(signatureCoseSign1);
1998 if (item == nullptr) {
1999 LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
2000 return {};
2001 }
2002 const cppbor::Array* array = item->asArray();
2003 if (array == nullptr) {
2004 LOG(ERROR) << "Value for COSE_Sign1 is not an array";
2005 return {};
2006 }
2007 if (array->size() != 4) {
2008 LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
2009 return {};
2010 }
2011
2012 vector<uint8_t> data;
2013 const cppbor::Simple* payloadAsSimple = (*array)[2]->asSimple();
2014 if (payloadAsSimple != nullptr) {
2015 if (payloadAsSimple->asNull() == nullptr) {
2016 LOG(ERROR) << "Value for payload is not null or a bstr";
2017 return {};
2018 }
2019 // payload is null, so |data| should be empty (as it is)
2020 } else {
2021 const cppbor::Bstr* payloadAsBstr = (*array)[2]->asBstr();
2022 if (payloadAsBstr == nullptr) {
2023 LOG(ERROR) << "Value for payload is not null or a bstr";
2024 return {};
2025 }
2026 // Copy payload into |data|
2027 data = payloadAsBstr->value();
2028 }
2029
2030 return data;
2031 }
2032
coseSignGetAlg(const vector<uint8_t> & signatureCoseSign1)2033 optional<int> coseSignGetAlg(const vector<uint8_t>& signatureCoseSign1) {
2034 auto [item, _, message] = cppbor::parse(signatureCoseSign1);
2035 if (item == nullptr) {
2036 LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
2037 return {};
2038 }
2039 const cppbor::Array* array = item->asArray();
2040 if (array == nullptr) {
2041 LOG(ERROR) << "Value for COSE_Sign1 is not an array";
2042 return {};
2043 }
2044 if (array->size() != 4) {
2045 LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
2046 return {};
2047 }
2048
2049 const cppbor::Bstr* protectedHeadersBytes = (*array)[0]->asBstr();
2050 if (protectedHeadersBytes == nullptr) {
2051 LOG(ERROR) << "Value for protectedHeaders is not a bstr";
2052 return {};
2053 }
2054 auto [item2, _2, message2] = cppbor::parse(protectedHeadersBytes->value());
2055 if (item2 == nullptr) {
2056 LOG(ERROR) << "Error parsing protectedHeaders: " << message2;
2057 return {};
2058 }
2059 const cppbor::Map* protectedHeaders = item2->asMap();
2060 if (protectedHeaders == nullptr) {
2061 LOG(ERROR) << "Decoded CBOR for protectedHeaders is not a map";
2062 return {};
2063 }
2064
2065 for (size_t n = 0; n < protectedHeaders->size(); n++) {
2066 auto [keyItem, valueItem] = (*protectedHeaders)[n];
2067 const cppbor::Int* number = keyItem->asInt();
2068 if (number == nullptr) {
2069 LOG(ERROR) << "Key item in top-level map is not a number";
2070 return {};
2071 }
2072 int label = number->value();
2073 if (label == COSE_LABEL_ALG) {
2074 const cppbor::Int* number = valueItem->asInt();
2075 if (number != nullptr) {
2076 return number->value();
2077 }
2078 LOG(ERROR) << "Value for COSE_LABEL_ALG label is not a number";
2079 return {};
2080 }
2081 }
2082 LOG(ERROR) << "Did not find COSE_LABEL_ALG label in protected headers";
2083 return {};
2084 }
2085
coseSignGetX5Chain(const vector<uint8_t> & signatureCoseSign1)2086 optional<vector<uint8_t>> coseSignGetX5Chain(const vector<uint8_t>& signatureCoseSign1) {
2087 auto [item, _, message] = cppbor::parse(signatureCoseSign1);
2088 if (item == nullptr) {
2089 LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
2090 return {};
2091 }
2092 const cppbor::Array* array = item->asArray();
2093 if (array == nullptr) {
2094 LOG(ERROR) << "Value for COSE_Sign1 is not an array";
2095 return {};
2096 }
2097 if (array->size() != 4) {
2098 LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
2099 return {};
2100 }
2101
2102 const cppbor::Map* unprotectedHeaders = (*array)[1]->asMap();
2103 if (unprotectedHeaders == nullptr) {
2104 LOG(ERROR) << "Value for unprotectedHeaders is not a map";
2105 return {};
2106 }
2107
2108 for (size_t n = 0; n < unprotectedHeaders->size(); n++) {
2109 auto [keyItem, valueItem] = (*unprotectedHeaders)[n];
2110 const cppbor::Int* number = keyItem->asInt();
2111 if (number == nullptr) {
2112 LOG(ERROR) << "Key item in top-level map is not a number";
2113 return {};
2114 }
2115 int label = number->value();
2116 if (label == COSE_LABEL_X5CHAIN) {
2117 const cppbor::Bstr* bstr = valueItem->asBstr();
2118 if (bstr != nullptr) {
2119 return bstr->value();
2120 }
2121 const cppbor::Array* array = valueItem->asArray();
2122 if (array != nullptr) {
2123 vector<uint8_t> certs;
2124 for (size_t m = 0; m < array->size(); m++) {
2125 const cppbor::Bstr* bstr = ((*array)[m])->asBstr();
2126 if (bstr == nullptr) {
2127 LOG(ERROR) << "Item in x5chain array is not a bstr";
2128 return {};
2129 }
2130 const vector<uint8_t>& certValue = bstr->value();
2131 certs.insert(certs.end(), certValue.begin(), certValue.end());
2132 }
2133 return certs;
2134 }
2135 LOG(ERROR) << "Value for x5chain label is not a bstr or array";
2136 return {};
2137 }
2138 }
2139 LOG(ERROR) << "Did not find x5chain label in unprotected headers";
2140 return {};
2141 }
2142
coseBuildToBeMACed(const vector<uint8_t> & encodedProtectedHeaders,const vector<uint8_t> & data,const vector<uint8_t> & detachedContent)2143 vector<uint8_t> coseBuildToBeMACed(const vector<uint8_t>& encodedProtectedHeaders,
2144 const vector<uint8_t>& data,
2145 const vector<uint8_t>& detachedContent) {
2146 cppbor::Array macStructure;
2147 macStructure.add("MAC0");
2148 macStructure.add(encodedProtectedHeaders);
2149
2150 // We currently don't support Externally Supplied Data (RFC 8152 section 4.3)
2151 // so external_aad is the empty bstr
2152 vector<uint8_t> emptyExternalAad;
2153 macStructure.add(emptyExternalAad);
2154
2155 // Next field is the payload, independently of how it's transported (RFC
2156 // 8152 section 4.4). Since our API specifies only one of |data| and
2157 // |detachedContent| can be non-empty, it's simply just the non-empty one.
2158 if (data.size() > 0) {
2159 macStructure.add(data);
2160 } else {
2161 macStructure.add(detachedContent);
2162 }
2163
2164 return macStructure.encode();
2165 }
2166
coseMac0(const vector<uint8_t> & key,const vector<uint8_t> & data,const vector<uint8_t> & detachedContent)2167 optional<vector<uint8_t>> coseMac0(const vector<uint8_t>& key, const vector<uint8_t>& data,
2168 const vector<uint8_t>& detachedContent) {
2169 cppbor::Map unprotectedHeaders;
2170 cppbor::Map protectedHeaders;
2171
2172 if (data.size() > 0 && detachedContent.size() > 0) {
2173 LOG(ERROR) << "data and detachedContent cannot both be non-empty";
2174 return {};
2175 }
2176
2177 protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_HMAC_256_256);
2178
2179 vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
2180 vector<uint8_t> toBeMACed = coseBuildToBeMACed(encodedProtectedHeaders, data, detachedContent);
2181
2182 optional<vector<uint8_t>> mac = hmacSha256(key, toBeMACed);
2183 if (!mac) {
2184 LOG(ERROR) << "Error MACing toBeMACed data";
2185 return {};
2186 }
2187
2188 cppbor::Array array;
2189 array.add(encodedProtectedHeaders);
2190 array.add(std::move(unprotectedHeaders));
2191 if (data.size() == 0) {
2192 cppbor::Null nullValue;
2193 array.add(std::move(nullValue));
2194 } else {
2195 array.add(data);
2196 }
2197 array.add(mac.value());
2198 return array.encode();
2199 }
2200
coseMacWithDigest(const vector<uint8_t> & digestToBeMaced,const vector<uint8_t> & data)2201 optional<vector<uint8_t>> coseMacWithDigest(const vector<uint8_t>& digestToBeMaced,
2202 const vector<uint8_t>& data) {
2203 cppbor::Map unprotectedHeaders;
2204 cppbor::Map protectedHeaders;
2205
2206 protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_HMAC_256_256);
2207
2208 vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
2209
2210 cppbor::Array array;
2211 array.add(encodedProtectedHeaders);
2212 array.add(std::move(unprotectedHeaders));
2213 if (data.size() == 0) {
2214 cppbor::Null nullValue;
2215 array.add(std::move(nullValue));
2216 } else {
2217 array.add(data);
2218 }
2219 array.add(digestToBeMaced);
2220 return array.encode();
2221 }
2222
2223 // ---------------------------------------------------------------------------
2224 // Utility functions specific to IdentityCredential.
2225 // ---------------------------------------------------------------------------
2226
chunkVector(const vector<uint8_t> & content,size_t maxChunkSize)2227 vector<vector<uint8_t>> chunkVector(const vector<uint8_t>& content, size_t maxChunkSize) {
2228 vector<vector<uint8_t>> ret;
2229
2230 size_t contentSize = content.size();
2231 if (contentSize <= maxChunkSize) {
2232 ret.push_back(content);
2233 return ret;
2234 }
2235
2236 size_t numChunks = (contentSize + maxChunkSize - 1) / maxChunkSize;
2237
2238 size_t pos = 0;
2239 for (size_t n = 0; n < numChunks; n++) {
2240 size_t size = contentSize - pos;
2241 if (size > maxChunkSize) {
2242 size = maxChunkSize;
2243 }
2244 auto begin = content.begin() + pos;
2245 auto end = content.begin() + pos + size;
2246 ret.emplace_back(vector<uint8_t>(begin, end));
2247 pos += maxChunkSize;
2248 }
2249
2250 return ret;
2251 }
2252
2253
2254 vector<uint8_t> testHardwareBoundKey = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
2255
getTestHardwareBoundKey()2256 const vector<uint8_t>& getTestHardwareBoundKey() {
2257 return testHardwareBoundKey;
2258 }
2259
2260 } // namespace support
2261 } // namespace identity
2262 } // namespace hardware
2263 } // namespace android
2264