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