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