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