blob: 57cdc9888eed6c74c00c2b9d68f000db2f27c99a [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) {
938 const keymaster_cert_chain_t* attestation_chain =
939 ::keymaster::getAttestationChain(KM_ALGORITHM_EC, nullptr);
940 if (attestation_chain == nullptr) {
941 LOG(ERROR) << "Error getting attestation chain";
942 return {};
943 }
944 if (expireTimeMilliSeconds == 0) {
945 if (attestation_chain->entry_count < 1) {
946 LOG(ERROR) << "Expected at least one entry in attestation chain";
947 return {};
948 }
949 keymaster_blob_t* bcBlob = &(attestation_chain->entries[0]);
950 const uint8_t* bcData = bcBlob->data;
951 auto bc = X509_Ptr(d2i_X509(nullptr, &bcData, bcBlob->data_length));
952 time_t bcNotAfter;
953 if (!parseAsn1Time(X509_get0_notAfter(bc.get()), &bcNotAfter)) {
954 LOG(ERROR) << "Error getting notAfter from batch certificate";
955 return {};
956 }
957 expireTimeMilliSeconds = bcNotAfter * 1000;
958 }
959 const keymaster_key_blob_t* attestation_signing_key =
960 ::keymaster::getAttestationKey(KM_ALGORITHM_EC, nullptr);
961 if (attestation_signing_key == nullptr) {
962 LOG(ERROR) << "Error getting attestation key";
963 return {};
964 }
965
Selene Huang06614b32020-11-19 20:14:14 -0800966 ::keymaster::X509_NAME_Ptr subjectName;
967 if (KM_ERROR_OK !=
968 ::keymaster::make_name_from_str("Android Identity Credential Key", &subjectName)) {
969 LOG(ERROR) << "Cannot create attestation subject";
970 return {};
971 }
972
973 vector<uint8_t> subject(i2d_X509_NAME(subjectName.get(), NULL));
974 unsigned char* subjectPtr = subject.data();
975
976 i2d_X509_NAME(subjectName.get(), &subjectPtr);
977
Selene Huang459cb802020-01-08 22:59:02 -0800978 ::keymaster::AuthorizationSet auth_set(
979 ::keymaster::AuthorizationSetBuilder()
980 .Authorization(::keymaster::TAG_ATTESTATION_CHALLENGE, challenge.data(),
981 challenge.size())
982 .Authorization(::keymaster::TAG_ACTIVE_DATETIME, activeTimeMilliSeconds)
983 // Even though identity attestation hal said the application
984 // id should be in software enforced authentication set,
985 // keymaster portable lib expect the input in this
986 // parameter because the software enforced in input to keymaster
987 // refers to the key software enforced properties. And this
988 // parameter refers to properties of the attestation which
989 // includes app id.
990 .Authorization(::keymaster::TAG_ATTESTATION_APPLICATION_ID,
991 applicationId.data(), applicationId.size())
Selene Huang06614b32020-11-19 20:14:14 -0800992 .Authorization(::keymaster::TAG_CERTIFICATE_SUBJECT, subject.data(),
993 subject.size())
Selene Huang459cb802020-01-08 22:59:02 -0800994 .Authorization(::keymaster::TAG_USAGE_EXPIRE_DATETIME, expireTimeMilliSeconds));
995
996 // Unique id and device id is not applicable for identity credential attestation,
997 // so we don't need to set those or application id.
998 ::keymaster::AuthorizationSet swEnforced(::keymaster::AuthorizationSetBuilder().Authorization(
999 ::keymaster::TAG_CREATION_DATETIME, activeTimeMilliSeconds));
1000
David Zeuthen34abaae2020-10-26 20:26:36 -04001001 ::keymaster::AuthorizationSetBuilder hwEnforcedBuilder =
Selene Huang459cb802020-01-08 22:59:02 -08001002 ::keymaster::AuthorizationSetBuilder()
1003 .Authorization(::keymaster::TAG_PURPOSE, KM_PURPOSE_SIGN)
1004 .Authorization(::keymaster::TAG_KEY_SIZE, 256)
1005 .Authorization(::keymaster::TAG_ALGORITHM, KM_ALGORITHM_EC)
1006 .Authorization(::keymaster::TAG_NO_AUTH_REQUIRED)
1007 .Authorization(::keymaster::TAG_DIGEST, KM_DIGEST_SHA_2_256)
1008 .Authorization(::keymaster::TAG_EC_CURVE, KM_EC_CURVE_P_256)
David Zeuthen34abaae2020-10-26 20:26:36 -04001009 .Authorization(::keymaster::TAG_OS_VERSION, 42)
1010 .Authorization(::keymaster::TAG_OS_PATCHLEVEL, 43);
Selene Huang459cb802020-01-08 22:59:02 -08001011
David Zeuthen34abaae2020-10-26 20:26:36 -04001012 // Only include TAG_IDENTITY_CREDENTIAL_KEY if it's not a test credential
1013 if (!isTestCredential) {
1014 hwEnforcedBuilder.Authorization(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY);
Selene Huang459cb802020-01-08 22:59:02 -08001015 }
David Zeuthen34abaae2020-10-26 20:26:36 -04001016 ::keymaster::AuthorizationSet hwEnforced(hwEnforcedBuilder);
Selene Huang459cb802020-01-08 22:59:02 -08001017
1018 keymaster_error_t error;
1019 ::keymaster::CertChainPtr cert_chain_out;
Selene Huang459cb802020-01-08 22:59:02 -08001020
David Zeuthen34abaae2020-10-26 20:26:36 -04001021 // Pretend to be implemented in a trusted environment just so we can pass
1022 // the VTS tests. Of course, this is a pretend-only game since hopefully no
1023 // relying party is ever going to trust our batch key and those keys above
1024 // it.
1025 //
1026 ::keymaster::PureSoftKeymasterContext context(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
1027
Selene Huang06614b32020-11-19 20:14:14 -08001028 error = generate_attestation_from_EVP(key, swEnforced, hwEnforced, auth_set, context,
1029 ::keymaster::kCurrentKeymasterVersion, *attestation_chain,
1030 *attestation_signing_key, &cert_chain_out);
Selene Huang459cb802020-01-08 22:59:02 -08001031
1032 if (KM_ERROR_OK != error || !cert_chain_out) {
1033 LOG(ERROR) << "Error generate attestation from EVP key" << error;
1034 return {};
1035 }
1036
1037 // translate certificate format from keymaster_cert_chain_t to vector<uint8_t>.
1038 vector<vector<uint8_t>> attestationCertificate;
1039 for (int i = 0; i < cert_chain_out->entry_count; i++) {
1040 attestationCertificate.insert(
1041 attestationCertificate.end(),
1042 vector<uint8_t>(
1043 cert_chain_out->entries[i].data,
1044 cert_chain_out->entries[i].data + cert_chain_out->entries[i].data_length));
1045 }
1046
1047 return attestationCertificate;
1048}
1049
1050optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
David Zeuthen34abaae2020-10-26 20:26:36 -04001051 const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
1052 bool isTestCredential) {
Selene Huang459cb802020-01-08 22:59:02 -08001053 auto ec_key = ::keymaster::EC_KEY_Ptr(EC_KEY_new());
1054 auto pkey = ::keymaster::EVP_PKEY_Ptr(EVP_PKEY_new());
1055 auto group = ::keymaster::EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
1056
1057 if (ec_key.get() == nullptr || pkey.get() == nullptr) {
1058 LOG(ERROR) << "Memory allocation failed";
1059 return {};
1060 }
1061
1062 if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
1063 EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
1064 LOG(ERROR) << "Error generating key";
1065 return {};
1066 }
1067
1068 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()) != 1) {
1069 LOG(ERROR) << "Error getting private key";
1070 return {};
1071 }
1072
David Zeuthen34abaae2020-10-26 20:26:36 -04001073 uint64_t nowMs = time(nullptr) * 1000;
1074 uint64_t expireTimeMs = 0; // Set to same as batch certificate
Selene Huang459cb802020-01-08 22:59:02 -08001075
David Zeuthen34abaae2020-10-26 20:26:36 -04001076 optional<vector<vector<uint8_t>>> attestationCert = createAttestation(
1077 pkey.get(), applicationId, challenge, nowMs, expireTimeMs, isTestCredential);
Selene Huang459cb802020-01-08 22:59:02 -08001078 if (!attestationCert) {
1079 LOG(ERROR) << "Error create attestation from key and challenge";
1080 return {};
1081 }
1082
1083 int size = i2d_PrivateKey(pkey.get(), nullptr);
1084 if (size == 0) {
1085 LOG(ERROR) << "Error generating public key encoding";
1086 return {};
1087 }
1088
1089 vector<uint8_t> keyPair(size);
1090 unsigned char* p = keyPair.data();
1091 i2d_PrivateKey(pkey.get(), &p);
1092
1093 return make_pair(keyPair, attestationCert.value());
1094}
1095
josephjang4821cee2020-06-03 10:57:38 +08001096optional<vector<vector<uint8_t>>> createAttestationForEcPublicKey(
1097 const vector<uint8_t>& publicKey, const vector<uint8_t>& challenge,
1098 const vector<uint8_t>& applicationId) {
1099 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
1100 auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
1101 if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
1102 1) {
1103 LOG(ERROR) << "Error decoding publicKey";
1104 return {};
1105 }
1106 auto ecKey = EC_KEY_Ptr(EC_KEY_new());
1107 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1108 if (ecKey.get() == nullptr || pkey.get() == nullptr) {
1109 LOG(ERROR) << "Memory allocation failed";
1110 return {};
1111 }
1112 if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
1113 LOG(ERROR) << "Error setting group";
1114 return {};
1115 }
1116 if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
1117 LOG(ERROR) << "Error setting point";
1118 return {};
1119 }
1120 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1121 LOG(ERROR) << "Error setting key";
1122 return {};
1123 }
1124
David Zeuthen34abaae2020-10-26 20:26:36 -04001125 uint64_t nowMs = time(nullptr) * 1000;
1126 uint64_t expireTimeMs = 0; // Set to same as batch certificate
josephjang4821cee2020-06-03 10:57:38 +08001127
1128 optional<vector<vector<uint8_t>>> attestationCert =
David Zeuthen34abaae2020-10-26 20:26:36 -04001129 createAttestation(pkey.get(), applicationId, challenge, nowMs, expireTimeMs,
1130 false /* isTestCredential */);
josephjang4821cee2020-06-03 10:57:38 +08001131 if (!attestationCert) {
1132 LOG(ERROR) << "Error create attestation from key and challenge";
1133 return {};
1134 }
1135
1136 return attestationCert.value();
1137}
1138
David Zeuthenc75ac312019-10-28 13:16:45 -04001139optional<vector<uint8_t>> createEcKeyPair() {
1140 auto ec_key = EC_KEY_Ptr(EC_KEY_new());
1141 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
David Zeuthenc75ac312019-10-28 13:16:45 -04001142 if (ec_key.get() == nullptr || pkey.get() == nullptr) {
1143 LOG(ERROR) << "Memory allocation failed";
1144 return {};
1145 }
1146
Selene Huang92b61d62020-03-04 02:24:16 -08001147 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
1148 if (group.get() == nullptr) {
1149 LOG(ERROR) << "Error creating EC group by curve name";
1150 return {};
1151 }
1152
David Zeuthenc75ac312019-10-28 13:16:45 -04001153 if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
1154 EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
1155 LOG(ERROR) << "Error generating key";
1156 return {};
1157 }
1158
1159 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()) != 1) {
1160 LOG(ERROR) << "Error getting private key";
1161 return {};
1162 }
1163
1164 int size = i2d_PrivateKey(pkey.get(), nullptr);
1165 if (size == 0) {
1166 LOG(ERROR) << "Error generating public key encoding";
1167 return {};
1168 }
1169 vector<uint8_t> keyPair;
1170 keyPair.resize(size);
1171 unsigned char* p = keyPair.data();
1172 i2d_PrivateKey(pkey.get(), &p);
1173 return keyPair;
1174}
1175
1176optional<vector<uint8_t>> ecKeyPairGetPublicKey(const vector<uint8_t>& keyPair) {
1177 const unsigned char* p = (const unsigned char*)keyPair.data();
1178 auto pkey = EVP_PKEY_Ptr(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, keyPair.size()));
1179 if (pkey.get() == nullptr) {
1180 LOG(ERROR) << "Error parsing keyPair";
1181 return {};
1182 }
1183
1184 auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
1185 if (ecKey.get() == nullptr) {
1186 LOG(ERROR) << "Failed getting EC key";
1187 return {};
1188 }
1189
1190 auto ecGroup = EC_KEY_get0_group(ecKey.get());
1191 auto ecPoint = EC_KEY_get0_public_key(ecKey.get());
1192 int size = EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0,
1193 nullptr);
1194 if (size == 0) {
1195 LOG(ERROR) << "Error generating public key encoding";
1196 return {};
1197 }
1198
1199 vector<uint8_t> publicKey;
1200 publicKey.resize(size);
1201 EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
1202 publicKey.size(), nullptr);
1203 return publicKey;
1204}
1205
1206optional<vector<uint8_t>> ecKeyPairGetPrivateKey(const vector<uint8_t>& keyPair) {
1207 const unsigned char* p = (const unsigned char*)keyPair.data();
1208 auto pkey = EVP_PKEY_Ptr(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, keyPair.size()));
1209 if (pkey.get() == nullptr) {
1210 LOG(ERROR) << "Error parsing keyPair";
1211 return {};
1212 }
1213
1214 auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
1215 if (ecKey.get() == nullptr) {
1216 LOG(ERROR) << "Failed getting EC key";
1217 return {};
1218 }
1219
1220 const BIGNUM* bignum = EC_KEY_get0_private_key(ecKey.get());
1221 if (bignum == nullptr) {
1222 LOG(ERROR) << "Error getting bignum from private key";
1223 return {};
1224 }
1225 vector<uint8_t> privateKey;
1226 privateKey.resize(BN_num_bytes(bignum));
1227 BN_bn2bin(bignum, privateKey.data());
1228 return privateKey;
1229}
1230
David Zeuthenef739512020-06-03 13:24:52 -04001231optional<vector<uint8_t>> ecPrivateKeyToKeyPair(const vector<uint8_t>& privateKey) {
1232 auto bn = BIGNUM_Ptr(BN_bin2bn(privateKey.data(), privateKey.size(), nullptr));
1233 if (bn.get() == nullptr) {
1234 LOG(ERROR) << "Error creating BIGNUM";
1235 return {};
1236 }
1237
1238 auto ecKey = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
1239 if (EC_KEY_set_private_key(ecKey.get(), bn.get()) != 1) {
1240 LOG(ERROR) << "Error setting private key from BIGNUM";
1241 return {};
1242 }
1243
1244 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1245 if (pkey.get() == nullptr) {
1246 LOG(ERROR) << "Memory allocation failed";
1247 return {};
1248 }
1249
1250 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1251 LOG(ERROR) << "Error getting private key";
1252 return {};
1253 }
1254
1255 int size = i2d_PrivateKey(pkey.get(), nullptr);
1256 if (size == 0) {
1257 LOG(ERROR) << "Error generating public key encoding";
1258 return {};
1259 }
1260 vector<uint8_t> keyPair;
1261 keyPair.resize(size);
1262 unsigned char* p = keyPair.data();
1263 i2d_PrivateKey(pkey.get(), &p);
1264 return keyPair;
1265}
1266
David Zeuthenc75ac312019-10-28 13:16:45 -04001267optional<vector<uint8_t>> ecKeyPairGetPkcs12(const vector<uint8_t>& keyPair, const string& name,
1268 const string& serialDecimal, const string& issuer,
1269 const string& subject, time_t validityNotBefore,
1270 time_t validityNotAfter) {
1271 const unsigned char* p = (const unsigned char*)keyPair.data();
1272 auto pkey = EVP_PKEY_Ptr(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, keyPair.size()));
1273 if (pkey.get() == nullptr) {
1274 LOG(ERROR) << "Error parsing keyPair";
1275 return {};
1276 }
1277
1278 auto x509 = X509_Ptr(X509_new());
1279 if (!x509.get()) {
1280 LOG(ERROR) << "Error creating X509 certificate";
1281 return {};
1282 }
1283
1284 if (!X509_set_version(x509.get(), 2 /* version 3, but zero-based */)) {
1285 LOG(ERROR) << "Error setting version to 3";
1286 return {};
1287 }
1288
1289 if (X509_set_pubkey(x509.get(), pkey.get()) != 1) {
1290 LOG(ERROR) << "Error setting public key";
1291 return {};
1292 }
1293
1294 BIGNUM* bignumSerial = nullptr;
1295 if (BN_dec2bn(&bignumSerial, serialDecimal.c_str()) == 0) {
1296 LOG(ERROR) << "Error parsing serial";
1297 return {};
1298 }
1299 auto bignumSerialPtr = BIGNUM_Ptr(bignumSerial);
1300 auto asnSerial = ASN1_INTEGER_Ptr(BN_to_ASN1_INTEGER(bignumSerial, nullptr));
1301 if (X509_set_serialNumber(x509.get(), asnSerial.get()) != 1) {
1302 LOG(ERROR) << "Error setting serial";
1303 return {};
1304 }
1305
1306 auto x509Issuer = X509_NAME_Ptr(X509_NAME_new());
1307 if (x509Issuer.get() == nullptr ||
1308 X509_NAME_add_entry_by_txt(x509Issuer.get(), "CN", MBSTRING_ASC,
1309 (const uint8_t*)issuer.c_str(), issuer.size(), -1 /* loc */,
1310 0 /* set */) != 1 ||
1311 X509_set_issuer_name(x509.get(), x509Issuer.get()) != 1) {
1312 LOG(ERROR) << "Error setting issuer";
1313 return {};
1314 }
1315
1316 auto x509Subject = X509_NAME_Ptr(X509_NAME_new());
1317 if (x509Subject.get() == nullptr ||
1318 X509_NAME_add_entry_by_txt(x509Subject.get(), "CN", MBSTRING_ASC,
1319 (const uint8_t*)subject.c_str(), subject.size(), -1 /* loc */,
1320 0 /* set */) != 1 ||
1321 X509_set_subject_name(x509.get(), x509Subject.get()) != 1) {
1322 LOG(ERROR) << "Error setting subject";
1323 return {};
1324 }
1325
1326 auto asnNotBefore = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotBefore));
1327 if (asnNotBefore.get() == nullptr || X509_set_notBefore(x509.get(), asnNotBefore.get()) != 1) {
1328 LOG(ERROR) << "Error setting notBefore";
1329 return {};
1330 }
1331
1332 auto asnNotAfter = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotAfter));
1333 if (asnNotAfter.get() == nullptr || X509_set_notAfter(x509.get(), asnNotAfter.get()) != 1) {
1334 LOG(ERROR) << "Error setting notAfter";
1335 return {};
1336 }
1337
1338 if (X509_sign(x509.get(), pkey.get(), EVP_sha256()) == 0) {
1339 LOG(ERROR) << "Error signing X509 certificate";
1340 return {};
1341 }
1342
1343 // Ideally we wouldn't encrypt it (we're only using this function for
1344 // sending a key-pair over binder to the Android app) but BoringSSL does not
1345 // support this: from pkcs8_x509.c in BoringSSL: "In OpenSSL, -1 here means
1346 // to use no encryption, which we do not currently support."
1347 //
1348 // Passing nullptr as |pass|, though, means "no password". So we'll do that.
1349 // Compare with the receiving side - CredstoreIdentityCredential.java - where
1350 // an empty char[] is passed as the password.
1351 //
1352 auto pkcs12 = PKCS12_Ptr(PKCS12_create(nullptr, name.c_str(), pkey.get(), x509.get(),
1353 nullptr, // ca
1354 0, // nid_key
1355 0, // nid_cert
1356 0, // iter,
1357 0, // mac_iter,
1358 0)); // keytype
1359 if (pkcs12.get() == nullptr) {
1360 char buf[128];
1361 long errCode = ERR_get_error();
1362 ERR_error_string_n(errCode, buf, sizeof buf);
1363 LOG(ERROR) << "Error creating PKCS12, code " << errCode << ": " << buf;
1364 return {};
1365 }
1366
1367 unsigned char* buffer = nullptr;
1368 int length = i2d_PKCS12(pkcs12.get(), &buffer);
1369 if (length < 0) {
1370 LOG(ERROR) << "Error encoding PKCS12";
1371 return {};
1372 }
1373 vector<uint8_t> pkcs12Bytes;
1374 pkcs12Bytes.resize(length);
1375 memcpy(pkcs12Bytes.data(), buffer, length);
1376 OPENSSL_free(buffer);
1377
1378 return pkcs12Bytes;
1379}
1380
1381optional<vector<uint8_t>> ecPublicKeyGenerateCertificate(
1382 const vector<uint8_t>& publicKey, const vector<uint8_t>& signingKey,
1383 const string& serialDecimal, const string& issuer, const string& subject,
1384 time_t validityNotBefore, time_t validityNotAfter) {
1385 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
1386 auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
1387 if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
1388 1) {
1389 LOG(ERROR) << "Error decoding publicKey";
1390 return {};
1391 }
1392 auto ecKey = EC_KEY_Ptr(EC_KEY_new());
1393 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1394 if (ecKey.get() == nullptr || pkey.get() == nullptr) {
1395 LOG(ERROR) << "Memory allocation failed";
1396 return {};
1397 }
1398 if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
1399 LOG(ERROR) << "Error setting group";
1400 return {};
1401 }
1402 if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
1403 LOG(ERROR) << "Error setting point";
1404 return {};
1405 }
1406 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1407 LOG(ERROR) << "Error setting key";
1408 return {};
1409 }
1410
1411 auto bn = BIGNUM_Ptr(BN_bin2bn(signingKey.data(), signingKey.size(), nullptr));
1412 if (bn.get() == nullptr) {
1413 LOG(ERROR) << "Error creating BIGNUM for private key";
1414 return {};
1415 }
1416 auto privEcKey = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
1417 if (EC_KEY_set_private_key(privEcKey.get(), bn.get()) != 1) {
1418 LOG(ERROR) << "Error setting private key from BIGNUM";
1419 return {};
1420 }
1421 auto privPkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1422 if (EVP_PKEY_set1_EC_KEY(privPkey.get(), privEcKey.get()) != 1) {
1423 LOG(ERROR) << "Error setting private key";
1424 return {};
1425 }
1426
1427 auto x509 = X509_Ptr(X509_new());
1428 if (!x509.get()) {
1429 LOG(ERROR) << "Error creating X509 certificate";
1430 return {};
1431 }
1432
1433 if (!X509_set_version(x509.get(), 2 /* version 3, but zero-based */)) {
1434 LOG(ERROR) << "Error setting version to 3";
1435 return {};
1436 }
1437
1438 if (X509_set_pubkey(x509.get(), pkey.get()) != 1) {
1439 LOG(ERROR) << "Error setting public key";
1440 return {};
1441 }
1442
1443 BIGNUM* bignumSerial = nullptr;
1444 if (BN_dec2bn(&bignumSerial, serialDecimal.c_str()) == 0) {
1445 LOG(ERROR) << "Error parsing serial";
1446 return {};
1447 }
1448 auto bignumSerialPtr = BIGNUM_Ptr(bignumSerial);
1449 auto asnSerial = ASN1_INTEGER_Ptr(BN_to_ASN1_INTEGER(bignumSerial, nullptr));
1450 if (X509_set_serialNumber(x509.get(), asnSerial.get()) != 1) {
1451 LOG(ERROR) << "Error setting serial";
1452 return {};
1453 }
1454
1455 auto x509Issuer = X509_NAME_Ptr(X509_NAME_new());
1456 if (x509Issuer.get() == nullptr ||
1457 X509_NAME_add_entry_by_txt(x509Issuer.get(), "CN", MBSTRING_ASC,
1458 (const uint8_t*)issuer.c_str(), issuer.size(), -1 /* loc */,
1459 0 /* set */) != 1 ||
1460 X509_set_issuer_name(x509.get(), x509Issuer.get()) != 1) {
1461 LOG(ERROR) << "Error setting issuer";
1462 return {};
1463 }
1464
1465 auto x509Subject = X509_NAME_Ptr(X509_NAME_new());
1466 if (x509Subject.get() == nullptr ||
1467 X509_NAME_add_entry_by_txt(x509Subject.get(), "CN", MBSTRING_ASC,
1468 (const uint8_t*)subject.c_str(), subject.size(), -1 /* loc */,
1469 0 /* set */) != 1 ||
1470 X509_set_subject_name(x509.get(), x509Subject.get()) != 1) {
1471 LOG(ERROR) << "Error setting subject";
1472 return {};
1473 }
1474
1475 auto asnNotBefore = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotBefore));
1476 if (asnNotBefore.get() == nullptr || X509_set_notBefore(x509.get(), asnNotBefore.get()) != 1) {
1477 LOG(ERROR) << "Error setting notBefore";
1478 return {};
1479 }
1480
1481 auto asnNotAfter = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotAfter));
1482 if (asnNotAfter.get() == nullptr || X509_set_notAfter(x509.get(), asnNotAfter.get()) != 1) {
1483 LOG(ERROR) << "Error setting notAfter";
1484 return {};
1485 }
1486
1487 if (X509_sign(x509.get(), privPkey.get(), EVP_sha256()) == 0) {
1488 LOG(ERROR) << "Error signing X509 certificate";
1489 return {};
1490 }
1491
1492 unsigned char* buffer = nullptr;
1493 int length = i2d_X509(x509.get(), &buffer);
1494 if (length < 0) {
1495 LOG(ERROR) << "Error DER encoding X509 certificate";
1496 return {};
1497 }
1498
1499 vector<uint8_t> certificate;
1500 certificate.resize(length);
1501 memcpy(certificate.data(), buffer, length);
1502 OPENSSL_free(buffer);
1503 return certificate;
1504}
1505
1506optional<vector<uint8_t>> ecdh(const vector<uint8_t>& publicKey,
1507 const vector<uint8_t>& privateKey) {
1508 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
1509 auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
1510 if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
1511 1) {
1512 LOG(ERROR) << "Error decoding publicKey";
1513 return {};
1514 }
1515 auto ecKey = EC_KEY_Ptr(EC_KEY_new());
1516 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1517 if (ecKey.get() == nullptr || pkey.get() == nullptr) {
1518 LOG(ERROR) << "Memory allocation failed";
1519 return {};
1520 }
1521 if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
1522 LOG(ERROR) << "Error setting group";
1523 return {};
1524 }
1525 if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
1526 LOG(ERROR) << "Error setting point";
1527 return {};
1528 }
1529 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1530 LOG(ERROR) << "Error setting key";
1531 return {};
1532 }
1533
1534 auto bn = BIGNUM_Ptr(BN_bin2bn(privateKey.data(), privateKey.size(), nullptr));
1535 if (bn.get() == nullptr) {
1536 LOG(ERROR) << "Error creating BIGNUM for private key";
1537 return {};
1538 }
1539 auto privEcKey = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
1540 if (EC_KEY_set_private_key(privEcKey.get(), bn.get()) != 1) {
1541 LOG(ERROR) << "Error setting private key from BIGNUM";
1542 return {};
1543 }
1544 auto privPkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1545 if (EVP_PKEY_set1_EC_KEY(privPkey.get(), privEcKey.get()) != 1) {
1546 LOG(ERROR) << "Error setting private key";
1547 return {};
1548 }
1549
1550 auto ctx = EVP_PKEY_CTX_Ptr(EVP_PKEY_CTX_new(privPkey.get(), NULL));
1551 if (ctx.get() == nullptr) {
1552 LOG(ERROR) << "Error creating context";
1553 return {};
1554 }
1555
1556 if (EVP_PKEY_derive_init(ctx.get()) != 1) {
1557 LOG(ERROR) << "Error initializing context";
1558 return {};
1559 }
1560
1561 if (EVP_PKEY_derive_set_peer(ctx.get(), pkey.get()) != 1) {
1562 LOG(ERROR) << "Error setting peer";
1563 return {};
1564 }
1565
1566 /* Determine buffer length for shared secret */
1567 size_t secretLen = 0;
1568 if (EVP_PKEY_derive(ctx.get(), NULL, &secretLen) != 1) {
1569 LOG(ERROR) << "Error determing length of shared secret";
1570 return {};
1571 }
1572 vector<uint8_t> sharedSecret;
1573 sharedSecret.resize(secretLen);
1574
1575 if (EVP_PKEY_derive(ctx.get(), sharedSecret.data(), &secretLen) != 1) {
1576 LOG(ERROR) << "Error deriving shared secret";
1577 return {};
1578 }
1579 return sharedSecret;
1580}
1581
1582optional<vector<uint8_t>> hkdf(const vector<uint8_t>& sharedSecret, const vector<uint8_t>& salt,
1583 const vector<uint8_t>& info, size_t size) {
1584 vector<uint8_t> derivedKey;
1585 derivedKey.resize(size);
1586 if (HKDF(derivedKey.data(), derivedKey.size(), EVP_sha256(), sharedSecret.data(),
1587 sharedSecret.size(), salt.data(), salt.size(), info.data(), info.size()) != 1) {
1588 LOG(ERROR) << "Error deriving key";
1589 return {};
1590 }
1591 return derivedKey;
1592}
1593
1594void removeLeadingZeroes(vector<uint8_t>& vec) {
1595 while (vec.size() >= 1 && vec[0] == 0x00) {
1596 vec.erase(vec.begin());
1597 }
1598}
1599
1600tuple<bool, vector<uint8_t>, vector<uint8_t>> ecPublicKeyGetXandY(
1601 const vector<uint8_t>& publicKey) {
1602 if (publicKey.size() != 65 || publicKey[0] != 0x04) {
1603 LOG(ERROR) << "publicKey is not in the expected format";
1604 return std::make_tuple(false, vector<uint8_t>(), vector<uint8_t>());
1605 }
1606 vector<uint8_t> x, y;
1607 x.resize(32);
1608 y.resize(32);
1609 memcpy(x.data(), publicKey.data() + 1, 32);
1610 memcpy(y.data(), publicKey.data() + 33, 32);
1611
1612 removeLeadingZeroes(x);
1613 removeLeadingZeroes(y);
1614
1615 return std::make_tuple(true, x, y);
1616}
1617
1618optional<vector<uint8_t>> certificateChainGetTopMostKey(const vector<uint8_t>& certificateChain) {
1619 vector<X509_Ptr> certs;
1620 if (!parseX509Certificates(certificateChain, certs)) {
1621 return {};
1622 }
1623 if (certs.size() < 1) {
1624 LOG(ERROR) << "No certificates in chain";
1625 return {};
1626 }
1627
David Zeuthenc75ac312019-10-28 13:16:45 -04001628 auto pkey = EVP_PKEY_Ptr(X509_get_pubkey(certs[0].get()));
1629 if (pkey.get() == nullptr) {
1630 LOG(ERROR) << "No public key";
1631 return {};
1632 }
1633
1634 auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
1635 if (ecKey.get() == nullptr) {
1636 LOG(ERROR) << "Failed getting EC key";
1637 return {};
1638 }
1639
1640 auto ecGroup = EC_KEY_get0_group(ecKey.get());
1641 auto ecPoint = EC_KEY_get0_public_key(ecKey.get());
1642 int size = EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0,
1643 nullptr);
1644 if (size == 0) {
1645 LOG(ERROR) << "Error generating public key encoding";
1646 return {};
1647 }
1648 vector<uint8_t> publicKey;
1649 publicKey.resize(size);
1650 EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
1651 publicKey.size(), nullptr);
1652 return publicKey;
1653}
1654
josephjang4821cee2020-06-03 10:57:38 +08001655optional<pair<size_t, size_t>> certificateFindPublicKey(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 auto pkey = EVP_PKEY_Ptr(X509_get_pubkey(certs[0].get()));
1666 if (pkey.get() == nullptr) {
1667 LOG(ERROR) << "No public key";
1668 return {};
1669 }
1670
1671 auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
1672 if (ecKey.get() == nullptr) {
1673 LOG(ERROR) << "Failed getting EC key";
1674 return {};
1675 }
1676
1677 auto ecGroup = EC_KEY_get0_group(ecKey.get());
1678 auto ecPoint = EC_KEY_get0_public_key(ecKey.get());
1679 int size = EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0,
1680 nullptr);
1681 if (size == 0) {
1682 LOG(ERROR) << "Error generating public key encoding";
1683 return {};
1684 }
1685 vector<uint8_t> publicKey;
1686 publicKey.resize(size);
1687 EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
1688 publicKey.size(), nullptr);
1689
1690 size_t publicKeyOffset = 0;
1691 size_t publicKeySize = (size_t)size;
1692 void* location = memmem((const void*)x509Certificate.data(), x509Certificate.size(),
1693 (const void*)publicKey.data(), publicKey.size());
1694
1695 if (location == NULL) {
1696 LOG(ERROR) << "Error finding publicKey from x509Certificate";
1697 return {};
1698 }
1699 publicKeyOffset = (size_t)((const char*)location - (const char*)x509Certificate.data());
1700
1701 return std::make_pair(publicKeyOffset, publicKeySize);
1702}
1703
1704optional<pair<size_t, size_t>> certificateTbsCertificate(const vector<uint8_t>& x509Certificate) {
1705 vector<X509_Ptr> certs;
1706 if (!parseX509Certificates(x509Certificate, certs)) {
1707 return {};
1708 }
1709 if (certs.size() < 1) {
1710 LOG(ERROR) << "No certificates in chain";
1711 return {};
1712 }
1713
1714 unsigned char* buf = NULL;
1715 int len = i2d_re_X509_tbs(certs[0].get(), &buf);
1716 if ((len < 0) || (buf == NULL)) {
1717 LOG(ERROR) << "fail to extract tbsCertificate in x509Certificate";
1718 return {};
1719 }
1720
1721 vector<uint8_t> tbsCertificate(len);
1722 memcpy(tbsCertificate.data(), buf, len);
1723
1724 size_t tbsCertificateOffset = 0;
1725 size_t tbsCertificateSize = (size_t)len;
1726 void* location = memmem((const void*)x509Certificate.data(), x509Certificate.size(),
1727 (const void*)tbsCertificate.data(), tbsCertificate.size());
1728
1729 if (location == NULL) {
1730 LOG(ERROR) << "Error finding tbsCertificate from x509Certificate";
1731 return {};
1732 }
1733 tbsCertificateOffset = (size_t)((const char*)location - (const char*)x509Certificate.data());
1734
1735 return std::make_pair(tbsCertificateOffset, tbsCertificateSize);
1736}
1737
David Zeuthen34abaae2020-10-26 20:26:36 -04001738optional<pair<time_t, time_t>> certificateGetValidity(const vector<uint8_t>& x509Certificate) {
1739 vector<X509_Ptr> certs;
1740 if (!parseX509Certificates(x509Certificate, certs)) {
1741 LOG(ERROR) << "Error parsing certificates";
1742 return {};
1743 }
1744 if (certs.size() < 1) {
1745 LOG(ERROR) << "No certificates in chain";
1746 return {};
1747 }
1748
1749 time_t notBefore;
1750 time_t notAfter;
1751 if (!parseAsn1Time(X509_get0_notBefore(certs[0].get()), &notBefore)) {
1752 LOG(ERROR) << "Error parsing notBefore";
1753 return {};
1754 }
1755
1756 if (!parseAsn1Time(X509_get0_notAfter(certs[0].get()), &notAfter)) {
1757 LOG(ERROR) << "Error parsing notAfter";
1758 return {};
1759 }
1760
1761 return std::make_pair(notBefore, notAfter);
1762}
1763
josephjang4821cee2020-06-03 10:57:38 +08001764optional<pair<size_t, size_t>> certificateFindSignature(const vector<uint8_t>& x509Certificate) {
1765 vector<X509_Ptr> certs;
1766 if (!parseX509Certificates(x509Certificate, certs)) {
1767 return {};
1768 }
1769 if (certs.size() < 1) {
1770 LOG(ERROR) << "No certificates in chain";
1771 return {};
1772 }
1773
1774 ASN1_BIT_STRING* psig;
1775 X509_ALGOR* palg;
1776 X509_get0_signature((const ASN1_BIT_STRING**)&psig, (const X509_ALGOR**)&palg, certs[0].get());
1777
1778 vector<char> signature(psig->length);
1779 memcpy(signature.data(), psig->data, psig->length);
1780
1781 size_t signatureOffset = 0;
1782 size_t signatureSize = (size_t)psig->length;
1783 void* location = memmem((const void*)x509Certificate.data(), x509Certificate.size(),
1784 (const void*)signature.data(), signature.size());
1785
1786 if (location == NULL) {
1787 LOG(ERROR) << "Error finding signature from x509Certificate";
1788 return {};
1789 }
1790 signatureOffset = (size_t)((const char*)location - (const char*)x509Certificate.data());
1791
1792 return std::make_pair(signatureOffset, signatureSize);
1793}
1794
David Zeuthenc75ac312019-10-28 13:16:45 -04001795// ---------------------------------------------------------------------------
1796// COSE Utility Functions
1797// ---------------------------------------------------------------------------
1798
1799vector<uint8_t> coseBuildToBeSigned(const vector<uint8_t>& encodedProtectedHeaders,
1800 const vector<uint8_t>& data,
1801 const vector<uint8_t>& detachedContent) {
1802 cppbor::Array sigStructure;
1803 sigStructure.add("Signature1");
1804 sigStructure.add(encodedProtectedHeaders);
1805
1806 // We currently don't support Externally Supplied Data (RFC 8152 section 4.3)
1807 // so external_aad is the empty bstr
1808 vector<uint8_t> emptyExternalAad;
1809 sigStructure.add(emptyExternalAad);
1810
1811 // Next field is the payload, independently of how it's transported (RFC
1812 // 8152 section 4.4). Since our API specifies only one of |data| and
1813 // |detachedContent| can be non-empty, it's simply just the non-empty one.
1814 if (data.size() > 0) {
1815 sigStructure.add(data);
1816 } else {
1817 sigStructure.add(detachedContent);
1818 }
1819 return sigStructure.encode();
1820}
1821
1822vector<uint8_t> coseEncodeHeaders(const cppbor::Map& protectedHeaders) {
1823 if (protectedHeaders.size() == 0) {
1824 cppbor::Bstr emptyBstr(vector<uint8_t>({}));
1825 return emptyBstr.encode();
1826 }
1827 return protectedHeaders.encode();
1828}
1829
1830// From https://tools.ietf.org/html/rfc8152
1831const int COSE_LABEL_ALG = 1;
1832const int COSE_LABEL_X5CHAIN = 33; // temporary identifier
1833
1834// From "COSE Algorithms" registry
1835const int COSE_ALG_ECDSA_256 = -7;
1836const int COSE_ALG_HMAC_256_256 = 5;
1837
1838bool ecdsaSignatureCoseToDer(const vector<uint8_t>& ecdsaCoseSignature,
1839 vector<uint8_t>& ecdsaDerSignature) {
1840 if (ecdsaCoseSignature.size() != 64) {
1841 LOG(ERROR) << "COSE signature length is " << ecdsaCoseSignature.size() << ", expected 64";
1842 return false;
1843 }
1844
1845 auto rBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data(), 32, nullptr));
1846 if (rBn.get() == nullptr) {
1847 LOG(ERROR) << "Error creating BIGNUM for r";
1848 return false;
1849 }
1850
1851 auto sBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data() + 32, 32, nullptr));
1852 if (sBn.get() == nullptr) {
1853 LOG(ERROR) << "Error creating BIGNUM for s";
1854 return false;
1855 }
1856
1857 ECDSA_SIG sig;
1858 sig.r = rBn.get();
1859 sig.s = sBn.get();
1860
1861 size_t len = i2d_ECDSA_SIG(&sig, nullptr);
1862 ecdsaDerSignature.resize(len);
1863 unsigned char* p = (unsigned char*)ecdsaDerSignature.data();
1864 i2d_ECDSA_SIG(&sig, &p);
1865
1866 return true;
1867}
1868
1869bool ecdsaSignatureDerToCose(const vector<uint8_t>& ecdsaDerSignature,
1870 vector<uint8_t>& ecdsaCoseSignature) {
1871 ECDSA_SIG* sig;
1872 const unsigned char* p = ecdsaDerSignature.data();
1873 sig = d2i_ECDSA_SIG(nullptr, &p, ecdsaDerSignature.size());
1874 if (sig == nullptr) {
1875 LOG(ERROR) << "Error decoding DER signature";
1876 return false;
1877 }
1878
1879 ecdsaCoseSignature.clear();
1880 ecdsaCoseSignature.resize(64);
David Benjamin45ff9aa2020-08-26 15:36:41 -04001881 if (BN_bn2binpad(ECDSA_SIG_get0_r(sig), ecdsaCoseSignature.data(), 32) != 32) {
David Zeuthenc75ac312019-10-28 13:16:45 -04001882 LOG(ERROR) << "Error encoding r";
1883 return false;
1884 }
David Benjamin45ff9aa2020-08-26 15:36:41 -04001885 if (BN_bn2binpad(ECDSA_SIG_get0_s(sig), ecdsaCoseSignature.data() + 32, 32) != 32) {
David Zeuthenc75ac312019-10-28 13:16:45 -04001886 LOG(ERROR) << "Error encoding s";
1887 return false;
1888 }
1889 return true;
1890}
1891
josephjang4821cee2020-06-03 10:57:38 +08001892optional<vector<uint8_t>> coseSignEcDsaWithSignature(const vector<uint8_t>& signatureToBeSigned,
1893 const vector<uint8_t>& data,
1894 const vector<uint8_t>& certificateChain) {
1895 if (signatureToBeSigned.size() != 64) {
1896 LOG(ERROR) << "Invalid size for signatureToBeSigned, expected 64 got "
1897 << signatureToBeSigned.size();
1898 return {};
1899 }
1900
1901 cppbor::Map unprotectedHeaders;
1902 cppbor::Map protectedHeaders;
1903
1904 protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_ECDSA_256);
1905
1906 if (certificateChain.size() != 0) {
1907 optional<vector<vector<uint8_t>>> certs = support::certificateChainSplit(certificateChain);
1908 if (!certs) {
1909 LOG(ERROR) << "Error splitting certificate chain";
1910 return {};
1911 }
1912 if (certs.value().size() == 1) {
1913 unprotectedHeaders.add(COSE_LABEL_X5CHAIN, certs.value()[0]);
1914 } else {
1915 cppbor::Array certArray;
1916 for (const vector<uint8_t>& cert : certs.value()) {
1917 certArray.add(cert);
1918 }
1919 unprotectedHeaders.add(COSE_LABEL_X5CHAIN, std::move(certArray));
1920 }
1921 }
1922
1923 vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
1924
1925 cppbor::Array coseSign1;
1926 coseSign1.add(encodedProtectedHeaders);
1927 coseSign1.add(std::move(unprotectedHeaders));
1928 if (data.size() == 0) {
1929 cppbor::Null nullValue;
1930 coseSign1.add(std::move(nullValue));
1931 } else {
1932 coseSign1.add(data);
1933 }
1934 coseSign1.add(signatureToBeSigned);
1935 vector<uint8_t> signatureCoseSign1;
1936 signatureCoseSign1 = coseSign1.encode();
1937
1938 return signatureCoseSign1;
1939}
1940
David Zeuthenc75ac312019-10-28 13:16:45 -04001941optional<vector<uint8_t>> coseSignEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data,
1942 const vector<uint8_t>& detachedContent,
1943 const vector<uint8_t>& certificateChain) {
1944 cppbor::Map unprotectedHeaders;
1945 cppbor::Map protectedHeaders;
1946
1947 if (data.size() > 0 && detachedContent.size() > 0) {
1948 LOG(ERROR) << "data and detachedContent cannot both be non-empty";
1949 return {};
1950 }
1951
1952 protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_ECDSA_256);
1953
1954 if (certificateChain.size() != 0) {
1955 optional<vector<vector<uint8_t>>> certs = support::certificateChainSplit(certificateChain);
1956 if (!certs) {
1957 LOG(ERROR) << "Error splitting certificate chain";
1958 return {};
1959 }
1960 if (certs.value().size() == 1) {
1961 unprotectedHeaders.add(COSE_LABEL_X5CHAIN, certs.value()[0]);
1962 } else {
1963 cppbor::Array certArray;
1964 for (const vector<uint8_t>& cert : certs.value()) {
1965 certArray.add(cert);
1966 }
1967 unprotectedHeaders.add(COSE_LABEL_X5CHAIN, std::move(certArray));
1968 }
1969 }
1970
1971 vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
1972 vector<uint8_t> toBeSigned =
1973 coseBuildToBeSigned(encodedProtectedHeaders, data, detachedContent);
1974
1975 optional<vector<uint8_t>> derSignature = signEcDsa(key, toBeSigned);
1976 if (!derSignature) {
1977 LOG(ERROR) << "Error signing toBeSigned data";
1978 return {};
1979 }
1980 vector<uint8_t> coseSignature;
1981 if (!ecdsaSignatureDerToCose(derSignature.value(), coseSignature)) {
1982 LOG(ERROR) << "Error converting ECDSA signature from DER to COSE format";
1983 return {};
1984 }
1985
1986 cppbor::Array coseSign1;
1987 coseSign1.add(encodedProtectedHeaders);
1988 coseSign1.add(std::move(unprotectedHeaders));
1989 if (data.size() == 0) {
1990 cppbor::Null nullValue;
1991 coseSign1.add(std::move(nullValue));
1992 } else {
1993 coseSign1.add(data);
1994 }
1995 coseSign1.add(coseSignature);
1996 vector<uint8_t> signatureCoseSign1;
1997 signatureCoseSign1 = coseSign1.encode();
1998 return signatureCoseSign1;
1999}
2000
2001bool coseCheckEcDsaSignature(const vector<uint8_t>& signatureCoseSign1,
2002 const vector<uint8_t>& detachedContent,
2003 const vector<uint8_t>& publicKey) {
2004 auto [item, _, message] = cppbor::parse(signatureCoseSign1);
2005 if (item == nullptr) {
2006 LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
2007 return false;
2008 }
2009 const cppbor::Array* array = item->asArray();
2010 if (array == nullptr) {
2011 LOG(ERROR) << "Value for COSE_Sign1 is not an array";
2012 return false;
2013 }
2014 if (array->size() != 4) {
2015 LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
2016 return false;
2017 }
2018
2019 const cppbor::Bstr* encodedProtectedHeadersBstr = (*array)[0]->asBstr();
2020 ;
2021 if (encodedProtectedHeadersBstr == nullptr) {
2022 LOG(ERROR) << "Value for encodedProtectedHeaders is not a bstr";
2023 return false;
2024 }
2025 const vector<uint8_t> encodedProtectedHeaders = encodedProtectedHeadersBstr->value();
2026
2027 const cppbor::Map* unprotectedHeaders = (*array)[1]->asMap();
2028 if (unprotectedHeaders == nullptr) {
2029 LOG(ERROR) << "Value for unprotectedHeaders is not a map";
2030 return false;
2031 }
2032
2033 vector<uint8_t> data;
2034 const cppbor::Simple* payloadAsSimple = (*array)[2]->asSimple();
2035 if (payloadAsSimple != nullptr) {
2036 if (payloadAsSimple->asNull() == nullptr) {
2037 LOG(ERROR) << "Value for payload is not null or a bstr";
2038 return false;
2039 }
2040 } else {
2041 const cppbor::Bstr* payloadAsBstr = (*array)[2]->asBstr();
2042 if (payloadAsBstr == nullptr) {
2043 LOG(ERROR) << "Value for payload is not null or a bstr";
2044 return false;
2045 }
2046 data = payloadAsBstr->value(); // TODO: avoid copy
2047 }
2048
2049 if (data.size() > 0 && detachedContent.size() > 0) {
2050 LOG(ERROR) << "data and detachedContent cannot both be non-empty";
2051 return false;
2052 }
2053
2054 const cppbor::Bstr* signatureBstr = (*array)[3]->asBstr();
2055 if (signatureBstr == nullptr) {
2056 LOG(ERROR) << "Value for signature is a bstr";
2057 return false;
2058 }
2059 const vector<uint8_t>& coseSignature = signatureBstr->value();
2060
2061 vector<uint8_t> derSignature;
2062 if (!ecdsaSignatureCoseToDer(coseSignature, derSignature)) {
2063 LOG(ERROR) << "Error converting ECDSA signature from COSE to DER format";
2064 return false;
2065 }
2066
2067 vector<uint8_t> toBeSigned =
2068 coseBuildToBeSigned(encodedProtectedHeaders, data, detachedContent);
2069 if (!checkEcDsaSignature(support::sha256(toBeSigned), derSignature, publicKey)) {
2070 LOG(ERROR) << "Signature check failed";
2071 return false;
2072 }
2073 return true;
2074}
2075
josephjang4821cee2020-06-03 10:57:38 +08002076// Extracts the signature (of the ToBeSigned CBOR) from a COSE_Sign1.
2077optional<vector<uint8_t>> coseSignGetSignature(const vector<uint8_t>& signatureCoseSign1) {
2078 auto [item, _, message] = cppbor::parse(signatureCoseSign1);
2079 if (item == nullptr) {
2080 LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
2081 return {};
2082 }
2083 const cppbor::Array* array = item->asArray();
2084 if (array == nullptr) {
2085 LOG(ERROR) << "Value for COSE_Sign1 is not an array";
2086 return {};
2087 }
2088 if (array->size() != 4) {
2089 LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
2090 return {};
2091 }
2092
2093 vector<uint8_t> signature;
2094 const cppbor::Bstr* signatureAsBstr = (*array)[3]->asBstr();
2095 if (signatureAsBstr == nullptr) {
2096 LOG(ERROR) << "Value for signature is not a bstr";
2097 return {};
2098 }
2099 // Copy payload into |data|
2100 signature = signatureAsBstr->value();
2101
2102 return signature;
2103}
2104
David Zeuthenc75ac312019-10-28 13:16:45 -04002105optional<vector<uint8_t>> coseSignGetPayload(const vector<uint8_t>& signatureCoseSign1) {
2106 auto [item, _, message] = cppbor::parse(signatureCoseSign1);
2107 if (item == nullptr) {
2108 LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
2109 return {};
2110 }
2111 const cppbor::Array* array = item->asArray();
2112 if (array == nullptr) {
2113 LOG(ERROR) << "Value for COSE_Sign1 is not an array";
2114 return {};
2115 }
2116 if (array->size() != 4) {
2117 LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
2118 return {};
2119 }
2120
2121 vector<uint8_t> data;
2122 const cppbor::Simple* payloadAsSimple = (*array)[2]->asSimple();
2123 if (payloadAsSimple != nullptr) {
2124 if (payloadAsSimple->asNull() == nullptr) {
2125 LOG(ERROR) << "Value for payload is not null or a bstr";
2126 return {};
2127 }
2128 // payload is null, so |data| should be empty (as it is)
2129 } else {
2130 const cppbor::Bstr* payloadAsBstr = (*array)[2]->asBstr();
2131 if (payloadAsBstr == nullptr) {
2132 LOG(ERROR) << "Value for payload is not null or a bstr";
2133 return {};
2134 }
2135 // Copy payload into |data|
2136 data = payloadAsBstr->value();
2137 }
2138
2139 return data;
2140}
2141
josephjang4821cee2020-06-03 10:57:38 +08002142optional<int> coseSignGetAlg(const vector<uint8_t>& signatureCoseSign1) {
2143 auto [item, _, message] = cppbor::parse(signatureCoseSign1);
2144 if (item == nullptr) {
2145 LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
2146 return {};
2147 }
2148 const cppbor::Array* array = item->asArray();
2149 if (array == nullptr) {
2150 LOG(ERROR) << "Value for COSE_Sign1 is not an array";
2151 return {};
2152 }
2153 if (array->size() != 4) {
2154 LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
2155 return {};
2156 }
2157
2158 const cppbor::Bstr* protectedHeadersBytes = (*array)[0]->asBstr();
2159 if (protectedHeadersBytes == nullptr) {
2160 LOG(ERROR) << "Value for protectedHeaders is not a bstr";
2161 return {};
2162 }
2163 auto [item2, _2, message2] = cppbor::parse(protectedHeadersBytes->value());
2164 if (item2 == nullptr) {
2165 LOG(ERROR) << "Error parsing protectedHeaders: " << message2;
2166 return {};
2167 }
2168 const cppbor::Map* protectedHeaders = item2->asMap();
2169 if (protectedHeaders == nullptr) {
2170 LOG(ERROR) << "Decoded CBOR for protectedHeaders is not a map";
2171 return {};
2172 }
2173
2174 for (size_t n = 0; n < protectedHeaders->size(); n++) {
2175 auto [keyItem, valueItem] = (*protectedHeaders)[n];
2176 const cppbor::Int* number = keyItem->asInt();
2177 if (number == nullptr) {
2178 LOG(ERROR) << "Key item in top-level map is not a number";
2179 return {};
2180 }
2181 int label = number->value();
2182 if (label == COSE_LABEL_ALG) {
2183 const cppbor::Int* number = valueItem->asInt();
2184 if (number != nullptr) {
2185 return number->value();
2186 }
2187 LOG(ERROR) << "Value for COSE_LABEL_ALG label is not a number";
2188 return {};
2189 }
2190 }
2191 LOG(ERROR) << "Did not find COSE_LABEL_ALG label in protected headers";
2192 return {};
2193}
2194
David Zeuthenc75ac312019-10-28 13:16:45 -04002195optional<vector<uint8_t>> coseSignGetX5Chain(const vector<uint8_t>& signatureCoseSign1) {
2196 auto [item, _, message] = cppbor::parse(signatureCoseSign1);
2197 if (item == nullptr) {
2198 LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
2199 return {};
2200 }
2201 const cppbor::Array* array = item->asArray();
2202 if (array == nullptr) {
2203 LOG(ERROR) << "Value for COSE_Sign1 is not an array";
2204 return {};
2205 }
2206 if (array->size() != 4) {
2207 LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
2208 return {};
2209 }
2210
2211 const cppbor::Map* unprotectedHeaders = (*array)[1]->asMap();
2212 if (unprotectedHeaders == nullptr) {
2213 LOG(ERROR) << "Value for unprotectedHeaders is not a map";
2214 return {};
2215 }
2216
2217 for (size_t n = 0; n < unprotectedHeaders->size(); n++) {
2218 auto [keyItem, valueItem] = (*unprotectedHeaders)[n];
2219 const cppbor::Int* number = keyItem->asInt();
2220 if (number == nullptr) {
2221 LOG(ERROR) << "Key item in top-level map is not a number";
2222 return {};
2223 }
2224 int label = number->value();
2225 if (label == COSE_LABEL_X5CHAIN) {
2226 const cppbor::Bstr* bstr = valueItem->asBstr();
2227 if (bstr != nullptr) {
2228 return bstr->value();
2229 }
2230 const cppbor::Array* array = valueItem->asArray();
2231 if (array != nullptr) {
2232 vector<uint8_t> certs;
2233 for (size_t m = 0; m < array->size(); m++) {
2234 const cppbor::Bstr* bstr = ((*array)[m])->asBstr();
2235 if (bstr == nullptr) {
2236 LOG(ERROR) << "Item in x5chain array is not a bstr";
2237 return {};
2238 }
2239 const vector<uint8_t>& certValue = bstr->value();
2240 certs.insert(certs.end(), certValue.begin(), certValue.end());
2241 }
2242 return certs;
2243 }
2244 LOG(ERROR) << "Value for x5chain label is not a bstr or array";
2245 return {};
2246 }
2247 }
2248 LOG(ERROR) << "Did not find x5chain label in unprotected headers";
2249 return {};
2250}
2251
2252vector<uint8_t> coseBuildToBeMACed(const vector<uint8_t>& encodedProtectedHeaders,
2253 const vector<uint8_t>& data,
2254 const vector<uint8_t>& detachedContent) {
2255 cppbor::Array macStructure;
2256 macStructure.add("MAC0");
2257 macStructure.add(encodedProtectedHeaders);
2258
2259 // We currently don't support Externally Supplied Data (RFC 8152 section 4.3)
2260 // so external_aad is the empty bstr
2261 vector<uint8_t> emptyExternalAad;
2262 macStructure.add(emptyExternalAad);
2263
2264 // Next field is the payload, independently of how it's transported (RFC
2265 // 8152 section 4.4). Since our API specifies only one of |data| and
2266 // |detachedContent| can be non-empty, it's simply just the non-empty one.
2267 if (data.size() > 0) {
2268 macStructure.add(data);
2269 } else {
2270 macStructure.add(detachedContent);
2271 }
2272
2273 return macStructure.encode();
2274}
2275
2276optional<vector<uint8_t>> coseMac0(const vector<uint8_t>& key, const vector<uint8_t>& data,
2277 const vector<uint8_t>& detachedContent) {
2278 cppbor::Map unprotectedHeaders;
2279 cppbor::Map protectedHeaders;
2280
2281 if (data.size() > 0 && detachedContent.size() > 0) {
2282 LOG(ERROR) << "data and detachedContent cannot both be non-empty";
2283 return {};
2284 }
2285
2286 protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_HMAC_256_256);
2287
2288 vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
2289 vector<uint8_t> toBeMACed = coseBuildToBeMACed(encodedProtectedHeaders, data, detachedContent);
2290
2291 optional<vector<uint8_t>> mac = hmacSha256(key, toBeMACed);
2292 if (!mac) {
2293 LOG(ERROR) << "Error MACing toBeMACed data";
2294 return {};
2295 }
2296
2297 cppbor::Array array;
2298 array.add(encodedProtectedHeaders);
2299 array.add(std::move(unprotectedHeaders));
2300 if (data.size() == 0) {
2301 cppbor::Null nullValue;
2302 array.add(std::move(nullValue));
2303 } else {
2304 array.add(data);
2305 }
2306 array.add(mac.value());
2307 return array.encode();
2308}
2309
josephjang4821cee2020-06-03 10:57:38 +08002310optional<vector<uint8_t>> coseMacWithDigest(const vector<uint8_t>& digestToBeMaced,
2311 const vector<uint8_t>& data) {
2312 cppbor::Map unprotectedHeaders;
2313 cppbor::Map protectedHeaders;
2314
2315 protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_HMAC_256_256);
2316
2317 vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
2318
2319 cppbor::Array array;
2320 array.add(encodedProtectedHeaders);
2321 array.add(std::move(unprotectedHeaders));
2322 if (data.size() == 0) {
2323 cppbor::Null nullValue;
2324 array.add(std::move(nullValue));
2325 } else {
2326 array.add(data);
2327 }
2328 array.add(digestToBeMaced);
2329 return array.encode();
2330}
2331
David Zeuthenc75ac312019-10-28 13:16:45 -04002332// ---------------------------------------------------------------------------
David Zeuthenc75ac312019-10-28 13:16:45 -04002333// Utility functions specific to IdentityCredential.
2334// ---------------------------------------------------------------------------
2335
David Zeuthen34abaae2020-10-26 20:26:36 -04002336optional<vector<uint8_t>> calcEMacKey(const vector<uint8_t>& privateKey,
2337 const vector<uint8_t>& publicKey,
2338 const vector<uint8_t>& sessionTranscriptBytes) {
2339 optional<vector<uint8_t>> sharedSecret = support::ecdh(publicKey, privateKey);
2340 if (!sharedSecret) {
2341 LOG(ERROR) << "Error performing ECDH";
2342 return {};
2343 }
2344 vector<uint8_t> salt = support::sha256(sessionTranscriptBytes);
2345 vector<uint8_t> info = {'E', 'M', 'a', 'c', 'K', 'e', 'y'};
2346 optional<vector<uint8_t>> derivedKey = support::hkdf(sharedSecret.value(), salt, info, 32);
2347 if (!derivedKey) {
2348 LOG(ERROR) << "Error performing HKDF";
2349 return {};
2350 }
2351 return derivedKey.value();
2352}
2353
2354optional<vector<uint8_t>> calcMac(const vector<uint8_t>& sessionTranscriptEncoded,
2355 const string& docType,
2356 const vector<uint8_t>& deviceNameSpacesEncoded,
2357 const vector<uint8_t>& eMacKey) {
2358 auto [sessionTranscriptItem, _, errMsg] = cppbor::parse(sessionTranscriptEncoded);
2359 if (sessionTranscriptItem == nullptr) {
2360 LOG(ERROR) << "Error parsing sessionTranscriptEncoded: " << errMsg;
2361 return {};
2362 }
2363 // The data that is MACed is ["DeviceAuthentication", sessionTranscript, docType,
2364 // deviceNameSpacesBytes] so build up that structure
2365 cppbor::Array deviceAuthentication =
2366 cppbor::Array()
2367 .add("DeviceAuthentication")
2368 .add(std::move(sessionTranscriptItem))
2369 .add(docType)
2370 .add(cppbor::Semantic(kSemanticTagEncodedCbor, deviceNameSpacesEncoded));
2371 vector<uint8_t> deviceAuthenticationBytes =
2372 cppbor::Semantic(kSemanticTagEncodedCbor, deviceAuthentication.encode()).encode();
2373 optional<vector<uint8_t>> calculatedMac =
2374 support::coseMac0(eMacKey, {}, // payload
2375 deviceAuthenticationBytes); // detached content
2376 return calculatedMac;
2377}
2378
David Zeuthenc75ac312019-10-28 13:16:45 -04002379vector<vector<uint8_t>> chunkVector(const vector<uint8_t>& content, size_t maxChunkSize) {
2380 vector<vector<uint8_t>> ret;
2381
2382 size_t contentSize = content.size();
2383 if (contentSize <= maxChunkSize) {
2384 ret.push_back(content);
2385 return ret;
2386 }
2387
2388 size_t numChunks = (contentSize + maxChunkSize - 1) / maxChunkSize;
2389
2390 size_t pos = 0;
2391 for (size_t n = 0; n < numChunks; n++) {
2392 size_t size = contentSize - pos;
2393 if (size > maxChunkSize) {
2394 size = maxChunkSize;
2395 }
2396 auto begin = content.begin() + pos;
2397 auto end = content.begin() + pos + size;
2398 ret.emplace_back(vector<uint8_t>(begin, end));
2399 pos += maxChunkSize;
2400 }
2401
2402 return ret;
2403}
2404
David Zeuthenc75ac312019-10-28 13:16:45 -04002405
2406vector<uint8_t> testHardwareBoundKey = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
2407
2408const vector<uint8_t>& getTestHardwareBoundKey() {
2409 return testHardwareBoundKey;
2410}
2411
David Zeuthenc75ac312019-10-28 13:16:45 -04002412} // namespace support
2413} // namespace identity
2414} // namespace hardware
2415} // namespace android